RFR: 8306889: Convert MethodTypeDescImpl parameter storage from array to immutable list [v4]

Chen Liang liach at openjdk.org
Wed May 24 02:44:06 UTC 2023


On Wed, 24 May 2023 02:29:09 GMT, Chen Liang <liach at openjdk.org> wrote:

>> This patch moves the parameters to an immutable list, to avoid allocations on `parameterList` as well. In addition, it fixes 8304932, the bug where if a caller keeps a reference to the array passed into `MethodTypeDesc.of`, the caller may mutate the Desc via the array and can create invalid MethodTypeDesc.
>> 
>> The latest benchmark results are available here: https://github.com/openjdk/jdk/pull/13186#issuecomment-1560378822
>> 
>> This patch has minor performance gains on `ofDescriptor` factory, even compared to Adam's patch that optimized `ofDescriptor` in #12945.
>> 
>> Benchmark of Oracle JDK 20: https://gist.github.com/683c6219e183cbc2b336224fc2c0d50a
>> Benchmark of this patch: https://gist.github.com/22be9371a2370fb4a7b44f1684750ec4
>> Benchmark of [asotona's patch](https://github.com/openjdk/jdk/pull/12945/files#diff-ac8e413d3e13532a2b0d34a90253c6ddd7a4f04082f792b9d076e9b5a33f2078): https://gist.github.com/eb98579c3b51cafae481049a95a78f80
>> 
>> [sotona vs this](https://jmh.morethan.io/?gists=eb98579c3b51cafae481049a95a78f80,22be9371a2370fb4a7b44f1684750ec4); [20 vs this](https://jmh.morethan.io/?gists=683c6219e183cbc2b336224fc2c0d50a,22be9371a2370fb4a7b44f1684750ec4); [20 vs sotona](https://jmh.morethan.io/?gists=683c6219e183cbc2b336224fc2c0d50a,eb98579c3b51cafae481049a95a78f80), for reference
>
> Chen Liang has updated the pull request incrementally with one additional commit since the last revision:
> 
>   reuse immutable list to avoid array allocation

Now updated to the latest MethodTypeDesc.of factories, this patch is ready for review and integration. Below is a few performance information about this patch.

This patch:

Benchmark                                                                     (descString)   Mode  Cnt      Score      Error   Units
MethodTypeDescDescriptor.computeDescriptorString   (Ljava/lang/Object;Ljava/lang/String;)I  thrpt    6  39518.106 ±  525.077  ops/ms
MethodTypeDescDescriptor.computeDescriptorString                                       ()V  thrpt    6  62312.500 ±  579.585  ops/ms
MethodTypeDescDescriptor.computeDescriptorString  ([IJLjava/lang/String;Z)Ljava/util/List;  thrpt    6  21856.065 ±  678.237  ops/ms
MethodTypeDescDescriptor.computeDescriptorString                     ()[Ljava/lang/String;  thrpt    6  57457.483 ± 1416.646  ops/ms

Benchmark                      Mode  Cnt      Score     Error  Units
RebuildMethodBodies.shared    thrpt    4  21684.365 ± 941.586  ops/s
RebuildMethodBodies.unshared  thrpt    4  15724.422 ± 153.420  ops/s

master:

Benchmark                                                                        (descString)   Mode  Cnt     Score     Error   Units
MethodTypeDescDescriptorOld.computeDescriptorString   (Ljava/lang/Object;Ljava/lang/String;)I  thrpt    6  6062.735 ±  61.852  ops/ms
MethodTypeDescDescriptorOld.computeDescriptorString                                       ()V  thrpt    6  8703.338 ± 205.429  ops/ms
MethodTypeDescDescriptorOld.computeDescriptorString  ([IJLjava/lang/String;Z)Ljava/util/List;  thrpt    6  5673.104 ±  62.810  ops/ms
MethodTypeDescDescriptorOld.computeDescriptorString                     ()[Ljava/lang/String;  thrpt    6  8232.874 ± 161.060  ops/ms

Benchmark                      Mode  Cnt      Score     Error  Units
RebuildMethodBodies.shared    thrpt    4  18317.288 ± 465.309  ops/s
RebuildMethodBodies.unshared  thrpt    4  13744.541 ± 399.263  ops/s


The Classfile API code generation and descriptor string computation speed up with this patch.

Additional benchmarks for this patch:

Benchmark                                     (kind)   Mode  Cnt       Score       Error   Units
MethodTypeDescConstruct.ofArrayBench         GENERIC  thrpt    6  203322.703 ±  5795.340  ops/ms
MethodTypeDescConstruct.ofArrayBench            VOID  thrpt    6  397200.234 ±  7467.524  ops/ms
MethodTypeDescConstruct.ofArrayBench        NO_PARAM  thrpt    6  398156.642 ±  7230.653  ops/ms
MethodTypeDescConstruct.ofArrayBench       ARBITRARY  thrpt    6   91751.039 ±  2451.052  ops/ms
MethodTypeDescConstruct.ofDescriptorBench    GENERIC  thrpt    6    8184.264 ±   185.177  ops/ms
MethodTypeDescConstruct.ofDescriptorBench       VOID  thrpt    6   68775.908 ±  2471.949  ops/ms
MethodTypeDescConstruct.ofDescriptorBench   NO_PARAM  thrpt    6   28129.233 ±   454.477  ops/ms
MethodTypeDescConstruct.ofDescriptorBench  ARBITRARY  thrpt    6    7634.086 ±   333.202  ops/ms
MethodTypeDescConstruct.ofListBench          GENERIC  thrpt    6  311382.640 ± 15817.487  ops/ms
MethodTypeDescConstruct.ofListBench             VOID  thrpt    6  371300.447 ±  2310.545  ops/ms
MethodTypeDescConstruct.ofListBench         NO_PARAM  thrpt    6  367942.613 ± 10068.395  ops/ms
MethodTypeDescConstruct.ofListBench        ARBITRARY  thrpt    6  199825.985 ±  5963.658  ops/ms

Shows that immutable parameter lists from users can be reused, and that using object representation to construct method type descs is always preferable to parsing descriptors; this is the same conclusion from #13671, that avoiding repeated parsing and reusing tokenization from classfile builder site actually improves performance.

Descriptor parsing is somewhat slower than in the initial benchmark, though the recent updates did not touch code in that area.

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

PR Comment: https://git.openjdk.org/jdk/pull/13186#issuecomment-1560378822


More information about the core-libs-dev mailing list