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

2023-05-26 Thread Chen Liang
On Wed, 24 May 2023 02:29:09 GMT, Chen Liang  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

The benefits of a list implementation over an array implementation are:
1. `parameterList()` is much faster, allowing more beautiful user code compared 
to manually unpacked iteration (immutable list factory doesn't allow using 
non-Object backing arrays)
2. `of(ClassDesc, List)` allows users to share immutable parameter lists than 
having to copy

> With https://github.com/openjdk/jdk/pull/13671, MethodTypeDesc is cached and 
> I wonder if this is no longer the bottleneck of ClassFile API performance.

The parsing is no more, but `descriptorString` is still a bottleneck. The 
master in the last benchmark already had 8306842 integrated.

In fact, I don't think argType array sharing goes far enough: in these 
modification methods and ofDescriptor, we can skip the array/list iteration 
validation if we can ensure the change parts alone have not produced an invalid 
method type (insertion of void, slot changes). I would postpone such in-depth 
sharing into a later issue, where we track the slot count information as well 
(to preemptively reject invalid resolveConstantDesc calls)

> Converting `argTypes` to an immutable list seems to be an extra step to make 
> it immutable - we need frozen arrays!!

Unfortunately, this is currently the only way general users have access to 
frozen arrays, where index-based access may be constant-folded, as `@Stable` is 
not generally available.

-

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


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

2023-05-26 Thread Mandy Chung
On Wed, 24 May 2023 02:29:09 GMT, Chen Liang  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

The microbenchmark shows the performance of using the `MethodTypeDesc` factory 
methods.  With [#13671](https://github.com/openjdk/jdk/pull/13671), 
`MethodTypeDesc` is cached and I wonder if this is no longer the bottleneck of 
ClassFile API performance.   

[JDK-8304932](https://bugs.openjdk.org/browse/JDK-8304932) is a bug that can 
simply be fixed by 

diff --git a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java 
b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java
index 738c4d68a43..ed23887c9ef 100644
--- a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java
+++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java
@@ -95,7 +95,7 @@ public sealed interface MethodTypeDesc
  * {@link ClassDesc} for {@code void}
  */
 static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) {
-return new MethodTypeDescImpl(returnDesc, paramDescs);
+return new MethodTypeDescImpl(returnDesc, paramDescs.clone());
 }
 
 /**
diff --git 
a/src/java.base/share/classes/java/lang/constant/MethodTypeDescImpl.java 
b/src/java.base/share/classes/java/lang/constant/MethodTypeDescImpl.java
index 4341c3fb56f..8586bfb5926 100644
--- a/src/java.base/share/classes/java/lang/constant/MethodTypeDescImpl.java
+++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDescImpl.java
@@ -41,7 +41,7 @@ import static java.util.Objects.requireNonNull;
  */
 final class MethodTypeDescImpl implements MethodTypeDesc {
 private final ClassDesc returnType;
-private final ClassDesc[] argTypes;
+private final ClassDesc[] argTypes; // trusted array
 
 /**
  * Constructs a {@linkplain MethodTypeDesc} with the specified return type
@@ -102,14 +102,14 @@ final class MethodTypeDescImpl implements MethodTypeDesc {
 
 @Override
 public MethodTypeDesc changeReturnType(ClassDesc returnType) {
-return MethodTypeDesc.of(returnType, argTypes);
+return new MethodTypeDescImpl(returnType, argTypes);
 }
 
 @Override
 public MethodTypeDesc changeParameterType(int index, ClassDesc paramType) {
 ClassDesc[] newArgs = argTypes.clone();
 newArgs[index] = paramType;
-return MethodTypeDesc.of(returnType, newArgs);
+return new MethodTypeDescImpl(returnType, newArgs);
 }
 
 @Override
@@ -120,7 +120,7 @@ final class MethodTypeDescImpl implements MethodTypeDesc {
 ClassDesc[] newArgs = new ClassDesc[argTypes.length - (end - start)];
 System.arraycopy(argTypes, 0, newArgs, 0, start);
 System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end);
-return MethodTypeDesc.of(returnType, newArgs);
+return new MethodTypeDescImpl(returnType, newArgs);
 }
 
 @Override
@@ -131,7 +131,7 @@ final class MethodTypeDescImpl implements MethodTypeDesc {
 System.arraycopy(argTypes, 0, newArgs, 0, pos);
 System.arraycopy(paramTypes, 0, newArgs, pos, paramTypes.length);
 System.arraycopy(argTypes, pos, newArgs, pos+paramTypes.length, 
argTypes.length - pos);
-return MethodTypeDesc.of(returnType, newArgs);
+return new MethodTypeDescImpl(returnType, newArgs);
 }
 
```  

I won't object to keep `argTypes` in an immutable list instead of an array.  
However, `MethodTypeDescImpl::ofDescriptor` has to bu

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

2023-05-23 Thread Chen Liang
On Wed, 24 May 2023 02:29:09 GMT, Chen Liang  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  thrpt6  39518.106 ±  525.077  
ops/ms
MethodTypeDescDescriptor.computeDescriptorString
   ()V  thrpt6  62312.500 ±  579.585  ops/ms
MethodTypeDescDescriptor.computeDescriptorString  
([IJLjava/lang/String;Z)Ljava/util/List;  thrpt6  21856.065 ±  678.237  
ops/ms
MethodTypeDescDescriptor.computeDescriptorString 
()[Ljava/lang/String;  thrpt6  57457.483 ± 1416.646  ops/ms

Benchmark  Mode  Cnt  Score Error  Units
RebuildMethodBodies.sharedthrpt4  21684.365 ± 941.586  ops/s
RebuildMethodBodies.unshared  thrpt4  15724.422 ± 153.420  ops/s

master:

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

Benchmark  Mode  Cnt  Score Error  Units
RebuildMethodBodies.sharedthrpt4  18317.288 ± 465.309  ops/s
RebuildMethodBodies.unshared  thrpt4  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  thrpt6  203322.703 ±  
5795.340  ops/ms
MethodTypeDescConstruct.ofArrayBenchVOID  thrpt6  397200.234 ±  
7467.524  ops/ms
MethodTypeDescConstruct.ofArrayBenchNO_PARAM  thrpt6  398156.642 ±  
7230.653  ops/ms
MethodTypeDescConstruct.ofArrayBench   ARBITRARY  thrpt6   91751.039 ±  
2451.052  ops/ms
MethodTypeDescConstruct.ofDescriptorBenchGENERIC  thrpt68184.264 ±  
 185.177  ops/ms
MethodTypeDescConstruct.ofDescriptorBench   VOID  thrpt6   68775.908 ±  
2471.949  ops/ms
MethodTypeDescConstruct.ofDescriptorBench   NO_PARAM  thrpt6   28129.233 ±  
 454.477  ops/ms
MethodTypeDescConstruct.ofDescriptorBench  ARBITRARY  thrpt67634.086 ±  
 333.202  ops/ms
MethodTypeDescConstruct.ofListBench  GENERIC  thrpt6  311382.640 ± 
15817.487  ops/ms
MethodTypeDescConstruct.ofListBench VOID  thrpt6  371300.447 ±  
2310.545  ops/ms
MethodTypeDescConstruct.ofListBench NO_PARAM  thrpt6  367942.613 ± 
10068.395  ops/ms
MethodTypeDescConstruct.ofListBenchARBITRARY  thrpt6  199825.985 ±  
5963.658  ops/ms

Shows that immutable para

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

2023-05-23 Thread Chen Liang
> 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.
> 
> 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

-

Changes:
  - all: https://git.openjdk.org/jdk/pull/13186/files
  - new: https://git.openjdk.org/jdk/pull/13186/files/6044b7ee..efc8018c

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=13186&range=03
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=13186&range=02-03

  Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/13186.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/13186/head:pull/13186

PR: https://git.openjdk.org/jdk/pull/13186