<i18n dev> RFR: 8335791: Speed ​​up j.u.Formatter & String.format [v3]

Shaojin Wen duke at openjdk.org
Fri Jul 5 22:02:38 UTC 2024


On Fri, 5 Jul 2024 20:43:51 GMT, Shaojin Wen <duke at openjdk.org> wrote:

>> String.format is widely used, and improving its performance is very meaningful. This PR can significantly improve the performance of String.format. Sorry, there are many changes, which will take a lot of time. I hope you can review it patiently.
>> 
>> 
>> Improved performance includes the following:
>> 
>> ## 1. Write directly during the parse process to reduce object allocation.
>> 
>> In the current Formatter implementation, some objects do not need to be allocated, such as:
>> 
>> 
>> class Formatter {
>>     public Formatter format(Locale l, String format, Object ... args) {
>>     	List<FormatString> fsa = parse(format);
>>     	// ...
>>     }
>> 
>>     static List<FormatString> parse(String s) {
>>     	ArrayList<FormatString> al = new ArrayList<>();
>> 
>>         while (i < max) {
>>             int n = s.indexOf('%', i);
>>             if (n < 0) {
>>                 // 
>>                 al.add(new FixedString(s, i, max));
>>             }
>>         }
>>     }
>> }
>> 
>> In the process of parsing, the content that is not a Specifier is directly appended without going through FixedString. By directly printing the parsed FormatString object, there is no need to construct a `List<FormatString> fsa` to store it.
>> 
>> ## 2. Fast path print
>> Use specialized FormatString implementations for single-character and single-width specifiers to avoid calling the large FormatSpecifier#print method.
>> 
>> ## 3. String.format directly calls j.u.Formatter
>> String.format directly calls j.u.Formatter via SharedSecrets to improve performance
>
> Shaojin Wen has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains six additional commits since the last revision:
> 
>  - Merge remote-tracking branch 'upstream/master' into optim_str_format_202407
>  - use unknownFormatConversion method construct UnknownFormatConversionException
>  - uppercase static final field name & code format
>  - add stable annotation
>  - replace cast to pattern matching
>  - speed up j.u.Formatter & String.format

The performance of the current version of decimalFormat is sometimes fast and sometimes slow. I don't know why.


make test TEST="micro:java.lang.StringFormat.decimalFormat"

# Benchmark: org.openjdk.bench.java.lang.StringFormat.decimalFormat

# Run progress: 0.00% complete, ETA 00:00:30
# Fork: 1 of 3
# Warmup Iteration   1: 438.502 ns/op
# Warmup Iteration   2: 473.917 ns/op
# Warmup Iteration   3: 468.569 ns/op
# Warmup Iteration   4: 411.787 ns/op
# Warmup Iteration   5: 417.982 ns/op
Iteration   1: 436.206 ns/op
Iteration   2: 422.356 ns/op
Iteration   3: 462.962 ns/op
Iteration   4: 408.021 ns/op
Iteration   5: 452.836 ns/op

# Run progress: 33.33% complete, ETA 00:00:22
# Fork: 2 of 3
# Warmup Iteration   1: 256.982 ns/op
# Warmup Iteration   2: 358.474 ns/op
# Warmup Iteration   3: 345.280 ns/op
# Warmup Iteration   4: 332.602 ns/op
# Warmup Iteration   5: 511.648 ns/op
Iteration   1: 478.953 ns/op
Iteration   2: 328.587 ns/op
Iteration   3: 195.851 ns/op
Iteration   4: 223.552 ns/op
Iteration   5: 228.569 ns/op

# Run progress: 66.67% complete, ETA 00:00:10
# Fork: 3 of 3
# Warmup Iteration   1: 446.023 ns/op
# Warmup Iteration   2: 360.855 ns/op
# Warmup Iteration   3: 540.793 ns/op
# Warmup Iteration   4: 537.336 ns/op
# Warmup Iteration   5: 248.511 ns/op
Iteration   1: 525.644 ns/op
Iteration   2: 463.829 ns/op
Iteration   3: 603.220 ns/op
Iteration   4: 248.151 ns/op
Iteration   5: 579.492 ns/op

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

PR Comment: https://git.openjdk.org/jdk/pull/20055#issuecomment-2211455189


More information about the i18n-dev mailing list