RFR: 8338532: Speed up the ClassFile API MethodTypeDesc#ofDescriptor [v3]
Shaojin Wen
duke at openjdk.org
Tue Aug 20 16:49:00 UTC 2024
On Tue, 20 Aug 2024 12:39:14 GMT, Shaojin Wen <duke at openjdk.org> wrote:
>> The current implementation of ofDescriptor puts return type and parameter types together in an ArrayList, and then splits them into return type and array of parameter types. This ArrayList creation is unnecessary, considering most descriptors only have few parameter types.
>>
>> By splitting return type and parameter types separately and scanning the descriptor first to get the number of parameters, we can just allocate an exact, trusted array for the resulting MethodTypeDesc without copy.
>
> Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision:
>
> remove specialization for `Ljava/lang/Object;`
After removing the specialization for `Ljava/lang/Object;`, the performance numbers on multiple platforms are as follows.
In scenarios where the number of parameters is greater than 9, the performance is slightly degraded. In most other scenarios, the performance is significantly improved.
## Benchmark Script
# baseline
git checkout c4697ac165d1b50834e2a653a9f5d025ea4cdaa2
make test TEST="micro:java.lang.constant.MethodTypeDescFactories.ofDescriptor"
# current
git checkout 43fbe47bec0ecd813ce82bedfd69e0ec7b16dd49
make test TEST="micro:java.lang.constant.MethodTypeDescFactories.ofDescriptor"
## Benchmark Numbers
### 2.1 MacBook M1 Pro
-# baseline
-Benchmark (descString) Mode Cnt Score Error Units
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/String;)I avgt 6 99.955 ? 1.148 ns/op
-MethodTypeDescFactories.ofDescriptor ()V avgt 6 3.852 ? 0.046 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; avgt 6 138.085 ? 1.482 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; avgt 6 142.119 ? 12.164 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; avgt 6 146.175 ? 19.254 ns/op
-MethodTypeDescFactories.ofDescriptor ()Ljava/lang/Object; avgt 6 23.943 ? 0.104 ns/op
-MethodTypeDescFactories.ofDescriptor ([IJLjava/lang/String;Z)Ljava/util/List; avgt 6 235.947 ? 55.958 ns/op
-MethodTypeDescFactories.ofDescriptor ()[Ljava/lang/String; avgt 6 20.620 ? 0.033 ns/op
-MethodTypeDescFactories.ofDescriptor (..IIJ)V avgt 6 256.069 ? 52.580 ns/op
-MethodTypeDescFactories.ofDescriptor ([III.Z[B..[.[B). avgt 6 339.915 ? 2.157 ns/op
-MethodTypeDescFactories.ofDescriptor (.....................). avgt 6 1116.437 ? 5.817 ns/op
+# current
+Benchmark (descString) Mode Cnt Score Error Units
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/String;)I avgt 6 94.979 ? 11.222 ns/op
+MethodTypeDescFactories.ofDescriptor ()V avgt 6 1.402 ? 0.012 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; avgt 6 123.435 ? 6.001 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; avgt 6 106.590 ? 5.809 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; avgt 6 126.491 ? 10.543 ns/op
+MethodTypeDescFactories.ofDescriptor ()Ljava/lang/Object; avgt 6 20.053 ? 0.154 ns/op
+MethodTypeDescFactories.ofDescriptor ([IJLjava/lang/String;Z)Ljava/util/List; avgt 6 64.872 ? 1.508 ns/op
+MethodTypeDescFactories.ofDescriptor ()[Ljava/lang/String; avgt 6 20.943 ? 0.038 ns/op
+MethodTypeDescFactories.ofDescriptor (..IIJ)V avgt 6 118.211 ? 1.680 ns/op
+MethodTypeDescFactories.ofDescriptor ([III.Z[B..[.[B). avgt 6 335.239 ? 2.006 ns/op
+MethodTypeDescFactories.ofDescriptor (.....................). avgt 6 1151.183 ? 18.441 ns/op
| pattern | baseline | current | delta |
| --- | --- | --- | --- |
| (Ljava/lang/Object;Ljava/lang/String;)I | 99.955 | 94.979 | 5.24% |
| ()V | 3.852 | 1.402 | 174.75% |
| (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; | 138.085 | 123.435 | 11.87% |
| (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; | 142.119 | 106.590 | 33.33% |
| (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; | 146.175 | 126.491 | 15.56% |
| ()Ljava/lang/Object; | 23.943 | 20.053 | 19.40% |
| ([IJLjava/lang/String;Z)Ljava/util/List; | 235.947 | 64.872 | 263.71% |
| ()[Ljava/lang/String; | 20.620 | 20.943 | -1.54% |
| (..IIJ)V | 256.069 | 118.211 | 116.62% |
| ([III.Z[B..[.[B). | 339.915 | 335.239 | 1.39% |
| (.....................). | 1116.437 | 1151.183 | -3.02% |
### 2.2 Aliyun ECS c8a
* AMD CPU (Linux x64)
# baseline
-Benchmark (descString) Mode Cnt Score Error Units
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/String;)I avgt 6 69.519 ± 0.085 ns/op
-MethodTypeDescFactories.ofDescriptor ()V avgt 6 10.187 ± 0.027 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; avgt 6 82.484 ± 0.133 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; avgt 6 82.436 ± 0.325 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; avgt 6 84.290 ± 0.427 ns/op
-MethodTypeDescFactories.ofDescriptor ()Ljava/lang/Object; avgt 6 20.850 ± 0.067 ns/op
-MethodTypeDescFactories.ofDescriptor ([IJLjava/lang/String;Z)Ljava/util/List; avgt 6 98.031 ± 0.233 ns/op
-MethodTypeDescFactories.ofDescriptor ()[Ljava/lang/String; avgt 6 26.571 ± 0.117 ns/op
-MethodTypeDescFactories.ofDescriptor (..IIJ)V avgt 6 143.015 ± 0.635 ns/op
-MethodTypeDescFactories.ofDescriptor ([III.Z[B..[.[B). avgt 6 359.922 ± 1.115 ns/op
-MethodTypeDescFactories.ofDescriptor (.....................). avgt 6 1138.662 ± 15.073 ns/op
+# current
+Benchmark (descString) Mode Cnt Score Error Units
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/String;)I avgt 6 52.467 ± 0.093 ns/op
+MethodTypeDescFactories.ofDescriptor ()V avgt 6 1.373 ± 0.005 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; avgt 6 74.534 ± 0.234 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; avgt 6 75.800 ± 0.542 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; avgt 6 77.573 ± 0.632 ns/op
+MethodTypeDescFactories.ofDescriptor ()Ljava/lang/Object; avgt 6 20.396 ± 0.058 ns/op
+MethodTypeDescFactories.ofDescriptor ([IJLjava/lang/String;Z)Ljava/util/List; avgt 6 78.385 ± 1.060 ns/op
+MethodTypeDescFactories.ofDescriptor ()[Ljava/lang/String; avgt 6 21.528 ± 0.047 ns/op
+MethodTypeDescFactories.ofDescriptor (..IIJ)V avgt 6 130.432 ± 0.393 ns/op
+MethodTypeDescFactories.ofDescriptor ([III.Z[B..[.[B). avgt 6 368.812 ± 0.791 ns/op
+MethodTypeDescFactories.ofDescriptor (.....................). avgt 6 1165.988 ± 7.120 ns/op
| pattern | baseline | current | delta |
| --- | --- | --- | --- |
| (Ljava/lang/Object;Ljava/lang/String;)I | 69.519 | 52.467 | 32.50% |
| ()V | 10.187 | 1.373 | 641.95% |
| (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; | 82.484 | 74.534 | 10.67% |
| (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; | 82.436 | 75.800 | 8.75% |
| (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; | 84.290 | 77.573 | 8.66% |
| ()Ljava/lang/Object; | 20.850 | 20.396 | 2.23% |
| ([IJLjava/lang/String;Z)Ljava/util/List; | 98.031 | 78.385 | 25.06% |
| ()[Ljava/lang/String; | 26.571 | 21.528 | 23.43% |
| (..IIJ)V | 143.015 | 130.432 | 9.65% |
| ([III.Z[B..[.[B). | 359.922 | 368.812 | -2.41% |
| (.....................). | 1138.662 | 1165.988 | -2.34% |
### 2.3 Aliyun ECS c8i
* Intel CPU (x64)
-# baseline
-Benchmark (descString) Mode Cnt Score Error Units
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/String;)I avgt 6 72.201 ± 0.681 ns/op
-MethodTypeDescFactories.ofDescriptor ()V avgt 6 13.187 ± 0.098 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; avgt 6 85.283 ± 0.842 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; avgt 6 85.462 ± 0.697 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; avgt 6 86.912 ± 0.836 ns/op
-MethodTypeDescFactories.ofDescriptor ()Ljava/lang/Object; avgt 6 21.551 ± 0.162 ns/op
-MethodTypeDescFactories.ofDescriptor ([IJLjava/lang/String;Z)Ljava/util/List; avgt 6 90.938 ± 0.299 ns/op
-MethodTypeDescFactories.ofDescriptor ()[Ljava/lang/String; avgt 6 22.450 ± 0.288 ns/op
-MethodTypeDescFactories.ofDescriptor (..IIJ)V avgt 6 152.704 ± 2.675 ns/op
-MethodTypeDescFactories.ofDescriptor ([III.Z[B..[.[B). avgt 6 385.490 ± 1.188 ns/op
-MethodTypeDescFactories.ofDescriptor (.....................). avgt 6 1213.829 ± 6.822 ns/op
+# current
+Benchmark (descString) Mode Cnt Score Error Units
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/String;)I avgt 6 53.754 ± 0.634 ns/op
+MethodTypeDescFactories.ofDescriptor ()V avgt 6 1.576 ± 0.002 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; avgt 6 74.727 ± 0.364 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; avgt 6 75.601 ± 0.407 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; avgt 6 77.970 ± 0.534 ns/op
+MethodTypeDescFactories.ofDescriptor ()Ljava/lang/Object; avgt 6 20.358 ± 0.154 ns/op
+MethodTypeDescFactories.ofDescriptor ([IJLjava/lang/String;Z)Ljava/util/List; avgt 6 76.490 ± 0.469 ns/op
+MethodTypeDescFactories.ofDescriptor ()[Ljava/lang/String; avgt 6 21.699 ± 0.089 ns/op
+MethodTypeDescFactories.ofDescriptor (..IIJ)V avgt 6 151.431 ± 2.457 ns/op
+MethodTypeDescFactories.ofDescriptor ([III.Z[B..[.[B). avgt 6 404.335 ± 7.515 ns/op
+MethodTypeDescFactories.ofDescriptor (.....................). avgt 6 1249.459 ± 14.023 ns/op
| pattern | baseline | current | delta |
| --- | --- | --- | --- |
| (Ljava/lang/Object;Ljava/lang/String;)I | 72.201 | 53.754 | 34.32% |
| ()V | 13.187 | 1.576 | 736.74% |
| (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; | 85.283 | 74.727 | 14.13% |
| (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; | 85.462 | 75.601 | 13.04% |
| (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; | 86.912 | 77.970 | 11.47% |
| ()Ljava/lang/Object; | 21.551 | 20.358 | 5.86% |
| ([IJLjava/lang/String;Z)Ljava/util/List; | 90.938 | 76.490 | 18.89% |
| ()[Ljava/lang/String; | 22.450 | 21.699 | 3.46% |
| (..IIJ)V | 152.704 | 151.431 | 0.84% |
| ([III.Z[B..[.[B). | 385.490 | 404.335 | -4.66% |
| (.....................). | 1213.829 | 1249.459 | -2.85% |
### 2.4 Aliyun ECS c8y
* Aliyun Yitian710 CPU (Linxu aarch64)
-# baseline
-Benchmark (descString) Mode Cnt Score Error Units
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/String;)I avgt 6 97.690 ± 0.388 ns/op
-MethodTypeDescFactories.ofDescriptor ()V avgt 6 5.866 ± 0.046 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; avgt 6 119.637 ± 0.626 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; avgt 6 122.579 ± 1.465 ns/op
-MethodTypeDescFactories.ofDescriptor (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; avgt 6 119.111 ± 0.819 ns/op
-MethodTypeDescFactories.ofDescriptor ()Ljava/lang/Object; avgt 6 37.169 ± 1.096 ns/op
-MethodTypeDescFactories.ofDescriptor ([IJLjava/lang/String;Z)Ljava/util/List; avgt 6 126.633 ± 2.096 ns/op
-MethodTypeDescFactories.ofDescriptor ()[Ljava/lang/String; avgt 6 31.170 ± 0.244 ns/op
-MethodTypeDescFactories.ofDescriptor (..IIJ)V avgt 6 197.251 ± 3.018 ns/op
-MethodTypeDescFactories.ofDescriptor ([III.Z[B..[.[B). avgt 6 572.934 ± 2.635 ns/op
-MethodTypeDescFactories.ofDescriptor (.....................). avgt 6 1751.494 ± 7.532 ns/op
+# current
+Benchmark (descString) Mode Cnt Score Error Units
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/String;)I avgt 6 73.081 ± 1.390 ns/op
+MethodTypeDescFactories.ofDescriptor ()V avgt 6 1.729 ± 0.019 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; avgt 6 104.971 ± 0.846 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; avgt 6 105.693 ± 0.963 ns/op
+MethodTypeDescFactories.ofDescriptor (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; avgt 6 108.848 ± 1.048 ns/op
+MethodTypeDescFactories.ofDescriptor ()Ljava/lang/Object; avgt 6 30.309 ± 0.181 ns/op
+MethodTypeDescFactories.ofDescriptor ([IJLjava/lang/String;Z)Ljava/util/List; avgt 6 108.834 ± 0.875 ns/op
+MethodTypeDescFactories.ofDescriptor ()[Ljava/lang/String; avgt 6 30.475 ± 0.531 ns/op
+MethodTypeDescFactories.ofDescriptor (..IIJ)V avgt 6 182.938 ± 2.459 ns/op
+MethodTypeDescFactories.ofDescriptor ([III.Z[B..[.[B). avgt 6 526.788 ± 7.156 ns/op
+MethodTypeDescFactories.ofDescriptor (.....................). avgt 6 1732.646 ± 10.851 ns/op
| pattern | baseline | current | delta |
| --- | --- | --- | --- |
| (Ljava/lang/Object;Ljava/lang/String;)I | 97.690 | 73.081 | 33.67% |
| ()V | 5.866 | 1.729 | 239.27% |
| (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; | 119.637 | 104.971 | 13.97% |
| (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; | 122.579 | 105.693 | 15.98% |
| (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer; | 119.111 | 108.848 | 9.43% |
| ()Ljava/lang/Object; | 37.169 | 30.309 | 22.63% |
| ([IJLjava/lang/String;Z)Ljava/util/List; | 126.633 | 108.834 | 16.35% |
| ()[Ljava/lang/String; | 31.170 | 30.475 | 2.28% |
| (..IIJ)V | 197.251 | 182.938 | 7.82% |
| ([III.Z[B..[.[B). | 572.934 | 526.788 | 8.76% |
| (.....................). | 1751.494 | 1732.646 | 1.09% |
-------------
PR Comment: https://git.openjdk.org/jdk/pull/20611#issuecomment-2299302549
More information about the core-libs-dev
mailing list