On 11/23/2019 10:40 PM, Brian Goetz wrote:


Finally, we can benchmark the current approach against the LDC approach on a per-Method basis.  The LDC approach may well be doing more work per Method, so it's a tradeoff to determine whether deferring that work is a win.

By this last bit, I mean JMH'ing:

    Method m1() {
       return Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
    }

vs

    Method m2() {
        return bootstrap(... constant bootstrap args for above ...)
    }


Thanks for the pointers, I did run one round on my machine - I don't have a dedicated one - so, maybe treat it with a fine grain of salt. The test code and results can be found here: https://gist.github.com/DasBrain/501fd5ac1e2ade2e28347ec666299473

Benchmark                              Mode  Cnt Score        Error  Units
ProxyFindMethod.getMethod             thrpt   25  1505594.515 ± 42238.663  ops/s ProxyFindMethod.lookupMethod          thrpt   25   760530.602 ± 25074.003  ops/s ProxyFindMethod.lookupMethodCachedMH  thrpt   25  4327814.284 ± 103456.616  ops/s

I wrote three tests, the first one (getMethod) uses the Class.forName().getMethod(), the second uses lookup.findVirtual to get the MethodHandle every iteration, while the third one caches it in a static final field.

My interpretation: If the method has to be looked up (and the VM has to do that at least once), then the old getMethod call is faster. I also suspect the Class.forName call to be optimized - on some old java versions, iirc pre-1.5, Foo.class was compiled into Class.forName("Foo"), so the JIT might do something there.
So, now I have to learn how to read assembly. Good.

Reply via email to