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

I see Brain talked about use InvokeDynamic to implement Java lambda capture
( 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 :)


On Wed, May 3, 2017 at 5:34 AM, Vladimir Ivanov <> 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: . 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 mailing list

Best Regards,
Wenlei Xie (谢文磊)

mlvm-dev mailing list

Reply via email to