RFR: 8343559: Optimize Class.getMethod(String, Class<?>...) for methods with no-arg

jengebr duke at openjdk.org
Wed Nov 6 15:36:28 UTC 2024


On Wed, 6 Nov 2024 14:15:42 GMT, jengebr <duke at openjdk.org> wrote:

> This change optimizes the runtime of `Class.getMethod(String, Class<?>[])` in two ways:
> 
> 1. While iterating across each Method to find a match (existing logic) it now compares parameter count before checking method name.  This check is substantially faster.
> 2. While iterating (existing logic) if the requested method has no arguments, the loop terminates early after finding one match.  This works because there can only be one zero-arg method with the matching name in the specific class.
> 
> A benchmark and unit tests are included; benchmark results (below) show an improvement in all cases, and an especially large gain when the immediate class contains the no-arg target.
> 
> Base:
> 
> Benchmark                          Mode  Cnt     Score    Error  Units
> ClassGetMethod.getConcreteFiveArg  avgt    6    90.866 ±  2.698  ns/op
> ClassGetMethod.getConcreteNoArg    avgt    6    72.472 ± 10.225  ns/op
> ClassGetMethod.getIntfFiveArg      avgt    6   198.524 ±  7.089  ns/op
> ClassGetMethod.getIntfNoArg        avgt    6   191.739 ±  4.695  ns/op
> ClassGetMethod.getNoSuchMethod     avgt   10  2254.308 ± 42.829  ns/op
> ClassGetMethod.getSuperFiveArg     avgt    6   165.897 ±  4.370  ns/op
> ClassGetMethod.getSuperNoArg       avgt    6   148.361 ±  4.573  ns/op
> 
> 
> Modified:
> 
> Benchmark                          Mode  Cnt     Score    Error  Units
> ClassGetMethod.getConcreteFiveArg  avgt    6    77.059 ±  2.644  ns/op
> ClassGetMethod.getConcreteNoArg    avgt    6    47.666 ±  6.544  ns/op
> ClassGetMethod.getIntfFiveArg      avgt    6   164.427 ±  4.356  ns/op
> ClassGetMethod.getIntfNoArg        avgt    6   161.256 ±  6.832  ns/op
> ClassGetMethod.getNoSuchMethod     avgt   10  2158.844 ± 43.716  ns/op
> ClassGetMethod.getSuperFiveArg     avgt    6   129.047 ±  4.414  ns/op
> ClassGetMethod.getSuperNoArg       avgt    6   123.728 ±  6.182  ns/op

> I have a patch trying to avoid MethodList allocation for getMethod lookup: [liachmodded at 789c72c](https://github.com/liachmodded/jdk/commit/789c72c4a258181f6fd7c75b9e2ad50b32d37982)

I would love this - the memory cost of `getMethod()` is surprisingly high.

> However, another approach is to update the cache for ReflectionData, so we compute a Map from name+parameter key to the most specific method, when we compute `getMethods()`. Note that if we cannot find the method in the immediately declared methods, we always have to explore all declared methods from superclasses and superinterfaces, which has the same cost as `getMethods()`.

I see the runtime advantage but am concerned by the memory usage.  Our Spring + Tomcat applications would generate a rather large cache.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/21929#issuecomment-2460087764


More information about the core-libs-dev mailing list