Loading classes with many methods is very expensive

Stanimir Simeonoff stanimir at riflexo.com
Sun Oct 26 22:21:31 UTC 2014


Great effort.

>From first glance: the hashCode and equals of MethodList use
m.getParameterTypes() which is cloned. I'd rather pay the collision costs
and rely on the default hashCode/equals of Method itself (hashCode ignores
the parameters). Possibly hashCode can include the returnType but equals
should be direct call to Method.equals.

Stanimir




On Sun, Oct 26, 2014 at 10:25 PM, Peter Levart <peter.levart at gmail.com>
wrote:

> Hi all,
>
> I revamped the Class.getMethods() implementation so that it is faster for
> common cases and O(n) at the same time, which makes Martin's test happy (at
> least in part that measures getMethods() speed - the class loading /
> linkage in VM is a separate issue).
>
> With the following test that loads all classes from rt.jar and calls
> getMethods() on each of them:
>
> http://cr.openjdk.java.net/~plevart/jdk9-dev/Class.
> getMethods/GetAllRtMethods.java
>
> And system property 'sun.reflect.noCaches=true' (so that we exercise the
> logic in every loop - not just 1st), original code prints:
>
> 19657 classes loaded in 1.987373401 seconds.
> 494141 methods obtained in 1.02493941 seconds.
> 494141 methods obtained in 0.905235658 seconds.
> 494141 methods obtained in 0.914434303 seconds.
> 494141 methods obtained in 0.887212805 seconds.
> 494141 methods obtained in 0.888929483 seconds.
> 494141 methods obtained in 0.883309141 seconds.
> 494141 methods obtained in 0.88341098 seconds.
> 494141 methods obtained in 0.897397146 seconds.
> 494141 methods obtained in 0.885677466 seconds.
> 494141 methods obtained in 0.895834176 seconds.
>
> Patched code does the same about 10% faster:
>
> 19657 classes loaded in 2.084409717 seconds.
> 494124 methods obtained in 0.915928578 seconds.
> 494124 methods obtained in 0.785342465 seconds.
> 494124 methods obtained in 0.784852619 seconds.
> 494124 methods obtained in 0.793450205 seconds.
> 494124 methods obtained in 0.849915078 seconds.
> 494124 methods obtained in 0.77835511 seconds.
> 494124 methods obtained in 0.764144701 seconds.
> 494124 methods obtained in 0.754122383 seconds.
> 494124 methods obtained in 0.747961897 seconds.
> 494124 methods obtained in 0.7489937 seconds.
>
> Martin's test prints on my computer with original code the following:
>
> Base class load time: 177.80 ms
> getDeclaredMethods: Methods: 65521, Total time: 35.79 ms, Time per method:
> 0.0005 ms
> getMethods        : Methods: 65530, Total time: 50.15 ms, Time per method:
> 0.0008 ms
> Derived class load time: 34015.70 ms
> getDeclaredMethods: Methods: 65521, Total time: 33.82 ms, Time per method:
> 0.0005 ms
> getMethods        : Methods: 65530, Total time: 8122.00 ms, Time per
> method: 0.1239 ms
>
> And with patched code this:
>
> Base class load time: 157.16 ms
> getDeclaredMethods: Methods: 65521, Total time: 65.77 ms, Time per method:
> 0.0010 ms
> getMethods        : Methods: 65530, Total time: 44.64 ms, Time per method:
> 0.0007 ms
> Derived class load time: 33996.69 ms
> getDeclaredMethods: Methods: 65521, Total time: 32.63 ms, Time per method:
> 0.0005 ms
> getMethods        : Methods: 65530, Total time: 92.12 ms, Time per method:
> 0.0014 ms
>
>
> Here's a webrev of the patch:
>
> http://cr.openjdk.java.net/~plevart/jdk9-dev/Class.getMethods/webrev.01/
>
> Patched code is simpler (65 lines gone) and I hope, easier to understand
> and change (I think a change in spec is coming in JDK9 which will handle
> abstract interface methods the same way as default, right Joel?)
>
> I also took the liberty to eliminate some redundant array and
> Field/Method/Constructor copies. get[Method0,Field0,Counstuctor0] now
> return 'root' objects. Copying is performed in methods that call them and
> expose the objects to any code outside java.lang.Class. Also, findFields()
> and findMethods() don't do copying of Field/Method objects themselves, but
> rather live that to methods that call them. getInterfaces() method now
> delegates to getInterfaces(boolean copyArray) so that internally, not array
> copying is performed.
>
> All 55 java/lang/reflect jtreg tests pass with this patch.
>
>
> Regards, Peter
>
>



More information about the core-libs-dev mailing list