On Sat, 17 Aug 2024 16:27:50 GMT, Shaojin Wen <d...@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.
>
> The following are the performance numbers on multiple platforms. When the 
> number of parameters is > 8, the performance will regress by about 33%. When 
> the number of parameters is <= 8, the performance will be significantly 
> improved or neutral.
> 
> ## 1. Benchmark script
> 
> # baseline
> git checkout 74066bcca82749722e6fee57469520d418bf3430
> make test TEST="micro:java.lang.constant.MethodTypeDescFactories.ofDescriptor"
> 
> # current
> git checkout c02d2306935d99685e34ef960aa72e10feb82a39
> make test TEST="micro:java.lang.constant.MethodTypeDescFactories.ofDescriptor"
> 
> 
> ## 2. Performance numbers
> 
> ### 2.1 Mac Book M1 Pro
> 
> -# baseline
> -Benchmark                                                         
> (descString)  Mode  Cnt     Score     Error  Units
> -MethodTypeDescFactories.ofDescriptor   
> (Ljava/lang/Object;Ljava/lang/String;)I  avgt    6   104.154 ?   2.636  ns/op
> -MethodTypeDescFactories.ofDescriptor                                       
> ()V  avgt    6     3.843 ?   0.014  ns/op
> -MethodTypeDescFactories.ofDescriptor  
> ([IJLjava/lang/String;Z)Ljava/util/List;  avgt    6   221.013 ?  81.200  ns/op
> -MethodTypeDescFactories.ofDescriptor                     
> ()[Ljava/lang/String;  avgt    6    20.603 ?   0.026  ns/op
> -MethodTypeDescFactories.ofDescriptor                                  
> (..IIJ)V  avgt    6   221.404 ? 189.754  ns/op
> -MethodTypeDescFactories.ofDescriptor                  
> (.....................).  avgt    6  1128.418 ?  16.850  ns/op
> 
> +# current
> +Benchmark                                                         
> (descString)  Mode  Cnt     Score    Error  Units
> +MethodTypeDescFactories.ofDescriptor   
> (Ljava/lang/Object;Ljava/lang/String;)I  avgt    6    53.900 ?  0.061  ns/op
> +MethodTypeDescFactories.ofDescriptor                                       
> ()V  avgt    6     3.609 ?  0.017  ns/op
> +MethodTypeDescFactories.ofDescriptor  
> ([IJLjava/lang/String;Z)Ljava/util/List;  avgt    6    69.666 ?  0.596  ns/op
> +MethodTypeDescFactories.ofDescriptor                     
> ()[Ljava/lang/String;  avgt    6    20.978 ?  0.197  ns/op
> +MethodTypeDescFactories.ofDescriptor                                  
> (..IIJ)V  avgt    6   126.968 ?  0.715  ns/op
> +MethodTypeDescFactories.ofDescriptor                  
> (.....................).  avgt    6  1651.624 ? 30.462  ns/op
> 
> 
> | descString | baseline  | current | delta |
> | --- | --- | --- | --- |
> | (Ljava/lang/Object;Ljava/lang/String;)I | 104.154 | 53.900 | 93.24% |
> | ()V | 3.843 | 3.609 | 6.48% |
> | ([IJLjava/lang/String;Z)Ljava/util/List; ...

@wenshao Do you think we should resort back to allocating an `ArrayList` if our 
long cannot encode the descriptor's offset info? I think you can add a case of 
10 args like `([III.Z[B..[.[B)` and see if your patch improves over the 
baseline. You can add this case to `MethodTypeDescFactories` too.

<details>
<summary>
Only look at this if your approach is still slower than ArrayList allocation in 
my given simpler case.
</summary>
My proposal for `paramTypes` is like:

 - Fast return if empty
 - Fast loop to fill up `lengths`
   - Break if we encounter the 9th params or a long field descriptor
 - At break, if `cur == len`, means fast path works, we go through fast path
 - Else, we fall back to the old path of using `ArrayList`; add elements 
collected in `lengths` and the element between the last of `lengths` and cur 
(so it's either 9th element or too long)

This approach completely avoids a 2nd scan.
</details>

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

PR Comment: https://git.openjdk.org/jdk/pull/20611#issuecomment-2295038272

Reply via email to