Re: Implementing Lambda with Capture support makes Metaspace fills LambdaForms$BMH class

2017-05-03 Thread John Rose
On May 3, 2017, at 9:37 PM, Wenlei Xie  wrote:
> 
> Thank you Vladimir for the help ! I see the point why MH.bindTo() is not a 
> good fit for implementing lambda capturing. 

A simple rule for using MHs is that they are designed to be another form of 
code.
Creating many of them at a high rate is likely to stress JVM in ways similar
to loading many small classes at a high rate.

So bindTo is really code customization, which is not the same thing as data 
capture.
The MH before bindTo is an algorithm with a variable "hole" in it, where the MH 
after
bindTo is a customized version of the algorithm, with the hole filed by a 
constant.
It's a little like a C++ template instance.

I'd like high-count bindTo to be cheaper, of course, but it's not the design 
center,
and it's not where we are investing optimization effort.  Maybe in the future.

— John___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev


Re: Implementing Lambda with Capture support makes Metaspace fills LambdaForms$BMH class

2017-05-03 Thread Wenlei Xie
Thank you Vladimir for the help ! I see the point why MH.bindTo() is not a
good fit for implementing lambda capturing.

We cannot easily directly pass the values from table explicitly to the
generated MethodHandle, as we allow UDF/extract function used in lambda
functions.

I see Brain talked about use InvokeDynamic to implement Java lambda capture
(http://wiki.jvmlangsummit.com/images/7/7b/Goetz-jvmls-lambda.pdf) and the
LambdaMetaFactoryBenchmark class, I did some benchmark and it seems to have
better performance for capture support :). However I do see some strange
performance regression after the invocation number exceeds some threshold,
which is probably better fit in a separate email thread :)

Best,
Wenlei

On Wed, May 3, 2017 at 5:34 AM, Vladimir Ivanov <
vladimir.x.iva...@oracle.com> wrote:

> Thanks for the report and for the test case, Wenlei.
>
> What you observe is an unfortunate consequence of LambdaForm
> customization. It was introduced to speedup invocations of non-constant
> method handles (MH.invoke/invokeExact on a method handle which isn't a
> constant during JIT compilation).
>
> As an example from your use case, in order to optimize for the value of
> bound argument, the JIT compiler has to "see" it during the compilation.
> The only way to achieve it right now is by issuing "specialized" bytecode
> for the particular method handle and that's exactly what happens during
> LambdaForm customization.
>
> The generated class should go away once the method handle it was generated
> for becomes unreachable, but it seems you construct plenty of method
> handles for every query.
>
> As a workaround, you can turn it off by specifying:
>   -Djava.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD=-1
>
> But I agree with Remi that it's a sign of a deeper problem in how you use
> method handles. MH.bindTo() always produces a new method handle and doesn't
> look like a good fit for implementing lambda capturing.
>
> Method handles are designed for fast invocation. Some non-trivial amount
> of work happens during method handle instantiation, so it should be avoided
> in hot code. From performance perspective, one-time usage of method handles
> never pays off. You should try to cache and reuse them in order to observe
> speedups.
>
> In particular, reusing the same method handle chain for all rows and
> passing the value (from the table) explicitly should lead to a better
> generated code.
>
> Best regards,
> Vladimir Ivanov
>
>
> On 5/2/17 10:29 PM, Wenlei Xie wrote:
>
>> Hi,
>>
>> We are implementing Lambda function with capture support in a SQL
>> Engine. We currently implement by compiling user-written Lambda
>> Expression into a MethodHandle. And use bindTo to captured fields. Thus
>> for each row we will have a Bound Method Handle.
>>
>> However, we found JVM will generate the byte code Bound Method Handle
>> once it's invoked more than 128 times. This cause in some cases (when
>> the table has large arrays), the Metaspace fills with generated
>> LambdaForm$BMH class.
>>
>> Here is the simple code to reproduce the
>> issue: https://github.com/wenleix/BMHTest . It looks we cannot increase
>> java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD beyond 128. Any
>> suggestions to implement Lambda with Capture Support on JVM?
>>
>> Thank you !!
>>
>> Best,
>> Wenlei
>>
>>
>>
>>
>>
>> ___
>> mlvm-dev mailing list
>> mlvm-dev@openjdk.java.net
>> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>>
>> ___
> mlvm-dev mailing list
> mlvm-dev@openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>



-- 
Best Regards,
Wenlei Xie (谢文磊)

Email: wenlei@gmail.com
___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev


Re: Implementing Lambda with Capture support makes Metaspace fills LambdaForms$BMH class

2017-05-03 Thread Vladimir Ivanov

Thanks for the report and for the test case, Wenlei.

What you observe is an unfortunate consequence of LambdaForm 
customization. It was introduced to speedup invocations of non-constant 
method handles (MH.invoke/invokeExact on a method handle which isn't a 
constant during JIT compilation).


As an example from your use case, in order to optimize for the value of 
bound argument, the JIT compiler has to "see" it during the compilation. 
The only way to achieve it right now is by issuing "specialized" 
bytecode for the particular method handle and that's exactly what 
happens during LambdaForm customization.


The generated class should go away once the method handle it was 
generated for becomes unreachable, but it seems you construct plenty of 
method handles for every query.


As a workaround, you can turn it off by specifying:
  -Djava.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD=-1

But I agree with Remi that it's a sign of a deeper problem in how you 
use method handles. MH.bindTo() always produces a new method handle and 
doesn't look like a good fit for implementing lambda capturing.


Method handles are designed for fast invocation. Some non-trivial amount 
of work happens during method handle instantiation, so it should be 
avoided in hot code. From performance perspective, one-time usage of 
method handles never pays off. You should try to cache and reuse them in 
order to observe speedups.


In particular, reusing the same method handle chain for all rows and 
passing the value (from the table) explicitly should lead to a better 
generated code.


Best regards,
Vladimir Ivanov

On 5/2/17 10:29 PM, Wenlei Xie wrote:

Hi,

We are implementing Lambda function with capture support in a SQL
Engine. We currently implement by compiling user-written Lambda
Expression into a MethodHandle. And use bindTo to captured fields. Thus
for each row we will have a Bound Method Handle.

However, we found JVM will generate the byte code Bound Method Handle
once it's invoked more than 128 times. This cause in some cases (when
the table has large arrays), the Metaspace fills with generated
LambdaForm$BMH class.

Here is the simple code to reproduce the
issue: https://github.com/wenleix/BMHTest . It looks we cannot increase
java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD beyond 128. Any
suggestions to implement Lambda with Capture Support on JVM?

Thank you !!

Best,
Wenlei





___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev


___
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev