Backport of JDK-8054221 into JDK 8u
Сергей Цыпанов
sergei.tsypanov at yandex.ru
Fri May 8 07:23:16 UTC 2020
Hello,
https://bugs.openjdk.java.net/browse/JDK-8054221 fixed in JDK9 significantly improves
performance of StringJoiner by replacing inner StringBuilder with String[].
I've backported the changes into JDK8u (patch attached) and measured performance with this benchmark:
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(jvmArgsAppend = {"-Xms2g", "-Xmx2g", "-XX:+UseParallelGC"})
public class StringJoinerBenchmark {
@Benchmark
public String stringJoiner(Data data) {
return joinWithStringJoiner(data.stringArray);
}
private static String joinWithStringJoiner(String[] stringArray) {
StringJoiner joiner = new StringJoiner(",", "[", "]");
for (String str : stringArray) {
joiner.add(str);
}
return joiner.toString();
}
@State(Scope.Thread)
public static class Data {
@Param({"1", "5", "10", "100"})
private int length;
@Param({"1", "5", "10", "100"})
private int count;
private String[] stringArray;
@Setup
public void setup() {
stringArray = new String[count];
String alphabet = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < count; i++) {
stringArray[i] = randomString(alphabet, length);
}
}
private String randomString(String alphabet, int length) {
char[] chars = alphabet.toCharArray();
ThreadLocalRandom random = ThreadLocalRandom.current();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char c = chars[random.nextInt(chars.length)];
sb.append(c);
}
return sb.toString();
}
}
}
On my machine I've got the following results (full output is available on https://gist.github.com/stsypanov/ee7483c6e4f3d5a711743a531baa049f):
Benchmark (count) (length) original patched Units
stringJoiner 1 1 39.4 ± 0.5 40.4 ± 0.1 ns/op
stringJoiner 1 5 41.1 ± 0.5 41.5 ± 0.1 ns/op
stringJoiner 1 10 45.0 ± 1.0 42.6 ± 0.2 ns/op
stringJoiner 1 100 111.3 ± 4.0 54.3 ± 0.1 ns/op
stringJoiner 5 1 102.3 ± 2.9 76.3 ± 0.3 ns/op
stringJoiner 5 5 124.9 ± 3.8 77.9 ± 0.4 ns/op
stringJoiner 5 10 146.8 ± 1.5 84.9 ± 0.3 ns/op
stringJoiner 5 100 425.0 ± 6.7 194.0 ± 0.7 ns/op
stringJoiner 10 1 204.1 ± 1.3 158.1 ± 0.9 ns/op
stringJoiner 10 5 266.1 ± 167.3 166.0 ± 0.7 ns/op
stringJoiner 10 10 258.7 ± 5.6 179.1 ± 0.6 ns/op
stringJoiner 10 100 932.0 ± 33.4 454.1 ± 2.2 ns/op
stringJoiner 100 1 1771.4 ± 39.5 1360.0 ± 21.0 ns/op
stringJoiner 100 5 2083.9 ± 42.2 1495.2 ± 23.6 ns/op
stringJoiner 100 10 2104.1 ± 24.7 1719.9 ± 19.2 ns/op
stringJoiner 100 100 7042.0 ± 162.9 4068.2 ± 112.8 ns/op
stringJoiner:·gc.alloc.rate.norm 1 1 168.0 ± 0.0 120.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 1 5 176.0 ± 0.0 136.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 1 10 184.0 ± 0.0 152.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 1 100 1016.0 ± 0.0 520.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 5 1 184.0 ± 0.0 152.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 5 5 312.0 ± 0.0 232.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 5 10 520.0 ± 0.0 328.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 5 100 4328.0 ± 0.0 2136.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 10 1 296.0 ± 0.0 280.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 10 5 536.0 ± 0.0 440.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 10 10 936.0 ± 0.0 632.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 10 100 8648.0 ± 0.0 4232.0 ± 0.0 B/op
stringJoiner:·gc.alloc.rate.norm 100 1 1744.0 ± 0.0 1976.0 ± 5.4 B/op
stringJoiner:·gc.alloc.rate.norm 100 5 6032.0 ± 0.0 3576.0 ± 5.4 B/op
stringJoiner:·gc.alloc.rate.norm 100 10 7032.0 ± 0.0 5576.0 ± 5.4 B/op
stringJoiner:·gc.alloc.rate.norm 100 100 73056.0 ± 0.0 41576.0 ± 5.4 B/op
The backport demonstrates significant improvement both for average time and consumed memory.
StringJoiner is widely used in JDK and in client code (esp. when using Collectors.joining()) so I think this is a valuable improvement.
Can we apply the attached patch to upcoming version of JDK8u?
Regards,
Sergey Tsypanov
-------------- next part --------------
A non-text attachment was scrubbed...
Name: sj.patch
Type: text/x-diff
Size: 15845 bytes
Desc: not available
URL: <https://mail.openjdk.java.net/pipermail/jdk8u-dev/attachments/20200508/28a40d14/sj-0001.patch>
More information about the jdk8u-dev
mailing list