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