jdk
jdk copied to clipboard
8335366: Improve String.format performance with fastpath
We need a String format solution with good performance. String Template was once expected, but it has been removed. j.u.Formatter is powerful, but its performance is not good enough.
This PR implements a subset of j.u.Formatter capabilities. The performance is good enough that it is a fastpath for commonly used functions. When the supported functions are exceeded, it will fall back to using j.u.Formatter.
The performance of this implementation is good enough, the fastpath has low detection cost, There is no noticeable performance degradation when falling back to j.u.Formatter via fastpath.
Below is a comparison of String.format and concat-based and StringBuilder:
- benchmark java code
public class StringFormat {
@Benchmark
public String stringIntFormat() {
return "%s %d".formatted(s, i);
}
@Benchmark
public String stringIntConcat() {
return s + " " + i;
}
@Benchmark
public String stringIntStringBuilder() {
return new StringBuilder(s).append(" ").append(i).toString();
}
}
- benchmark number on macbook m1 pro
Benchmark Mode Cnt Score Error Units
StringFormat.stringIntConcat avgt 15 6.541 ? 0.056 ns/op
StringFormat.stringIntFormat avgt 15 17.399 ? 0.133 ns/op
StringFormat.stringIntStringBuilder avgt 15 8.004 ? 0.063 ns/op
From the above data, we can see that the implementation of fastpath reduces the performance difference between String.format and StringBuilder from 10 times to 2~3 times.
The implementation of fastpath supports the following four specifiers, which can appear at most twice and support a width of 1 to 9.
d
x
X
s
If necessary, we can add a few more.
Below is a comparison of performance numbers running on a MacBook M1, showing a significant performance improvement.
-Benchmark Mode Cnt Score Error Units (baseline)
-StringFormat.complexFormat avgt 15 895.954 ? 52.541 ns/op
-StringFormat.decimalFormat avgt 15 277.420 ? 18.254 ns/op
-StringFormat.stringFormat avgt 15 66.787 ? 2.715 ns/op
-StringFormat.stringIntFormat avgt 15 81.046 ? 1.879 ns/op
-StringFormat.widthStringFormat avgt 15 38.897 ? 0.114 ns/op
-StringFormat.widthStringIntFormat avgt 15 109.841 ? 1.028 ns/op
+Benchmark Mode Cnt Score Error Units (current f925339e93fdf7a281462554ce5d73139bd0f0cd)
+StringFormat.complexFormat avgt 15 863.156 ? 42.140 ns/op
+StringFormat.decimalFormat avgt 15 287.342 ? 19.896 ns/op
+StringFormat.stringFormat avgt 15 6.738 ? 0.027 ns/op
+StringFormat.stringIntFormat avgt 15 17.046 ? 0.090 ns/op
+StringFormat.widthStringFormat avgt 15 8.993 ? 0.073 ns/op
+StringFormat.widthStringIntFormat avgt 15 17.602 ? 0.014 ns/op
Progress
- [ ] Change must be properly reviewed (1 review required, with at least 1 Reviewer)
- [x] Change must not contain extraneous whitespace
- [x] Commit message must refer to an issue
Issue
- JDK-8335366: Improve String.format performance with fastpath (Enhancement - P4)
Reviewing
Using git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/19956/head:pull/19956
$ git checkout pull/19956
Update a local copy of the PR:
$ git checkout pull/19956
$ git pull https://git.openjdk.org/jdk.git pull/19956/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 19956
View PR using the GUI difftool:
$ git pr show -t 19956
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/19956.diff