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

Chen Liang liach at openjdk.org
Wed Nov 6 15:23:38 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

Changes requested by liach (Reviewer).

src/java.base/share/classes/java/lang/PublicMethods.java line 108:

> 106:                                Class<?>[] ptypes) {
> 107:             // check for matching param types length, then name, then param type equality
> 108:             return method.getParameterCount() == ptypes.length &&

Length check is already present in `equals`.  If you want this fast path, I think moving arrays equals check first is better.

src/java.base/share/classes/java/lang/PublicMethods.java line 157:

> 155:                         head = tail = new MethodList(method);
> 156:                         if (ptypes.length == 0) {
> 157:                             // zero args can only have one match - stop looking

This is wrong: if superclass has `Object work()` and this class has `Integer work()`, bytecode for this class will have a synthetic final `Object work()` that delegates call to `Integer work()`.

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

PR Review: https://git.openjdk.org/jdk/pull/21929#pullrequestreview-2418640017
PR Review Comment: https://git.openjdk.org/jdk/pull/21929#discussion_r1831230782
PR Review Comment: https://git.openjdk.org/jdk/pull/21929#discussion_r1831232688


More information about the core-libs-dev mailing list