I am running Windows x64. Windows 11 Pro 24H2 Intel(R) Core(TM) i7-1370P
On Mon, Jul 21, 2025 at 4:59 PM Chen Liang <chen.l.li...@oracle.com> wrote: > I finally came around and ran the benchmark on my linux-x64 device; > however, I could not produce your results where String is significantly > slower than StringBuilder. > > This is the results I've got: > > Benchmark (data) Mode Cnt > Score Error Units > CharSequenceCharAtBenchmark.testString ascii avgt 5 > 668.649 ± 13.895 ns/op > CharSequenceCharAtBenchmark.testString non-ascii avgt 5 > 651.903 ± 7.240 ns/op > CharSequenceCharAtBenchmark.testStringBuilder ascii avgt 5 > 673.802 ± 26.260 ns/op > CharSequenceCharAtBenchmark.testStringBuilder non-ascii avgt 5 > 657.374 ± 35.785 ns/op > > I think we might have more clue - are you testing on a macosx-aarch64 > machine or some other platform? It might be that on some platforms, there > are some problems in the hand-written assemblies for the intrinsics which > contribute to this slowdown, instead of a problem with the C2 IR. > > Chen > ------------------------------ > *From:* core-libs-dev <core-libs-dev-r...@openjdk.org> on behalf of Brett > Okken <brett.okken...@gmail.com> > *Sent:* Monday, July 21, 2025 4:01 PM > *To:* Roger Riggs <roger.ri...@oracle.com> > *Cc:* core-libs-dev@openjdk.org <core-libs-dev@openjdk.org> > *Subject:* Re: String.charAt vs StringBuilder.charAt performance > > Updating to have different test methods for each representation did remove > the difference for the non-ascii String case for the jdk 21+ releases. > However, the ascii (latin) strings are still slower with String than > StringBuilder. > > How does C2 then handle something like StringCharBuffer wrapping a > CharSequence for all of it's get operations: > > https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/StringCharBuffer.java#L88-L97 > > Which is then used by CharBufferSpliterator > > https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/CharBufferSpliterator.java > > And by many CharsetEncoder impls when either source or destination is not > backed by array (which would be the case if StringCharBuffer used): > > https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/sun/nio/cs/UTF_8.java#L517 > > https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/sun/nio/cs/UnicodeEncoder.java#L81 > > > > jdk 17 > Benchmark (data) Mode Cnt > Score Error Units > CharSequenceCharAtBenchmark.testString ascii avgt 3 > 1429.358 ± 623.424 ns/op > CharSequenceCharAtBenchmark.testString non-ascii avgt 3 > 705.282 ± 233.453 ns/op > CharSequenceCharAtBenchmark.testStringBuilder ascii avgt 3 > 724.138 ± 267.346 ns/op > CharSequenceCharAtBenchmark.testStringBuilder non-ascii avgt 3 > 718.357 ± 864.066 ns/op > > jdk 21 > Benchmark (data) Mode Cnt > Score Error Units > CharSequenceCharAtBenchmark.testString ascii avgt 3 > 1087.024 ┬▒ 235.082 ns/op > CharSequenceCharAtBenchmark.testString non-ascii avgt 3 > 687.520 ┬▒ 747.532 ns/op > CharSequenceCharAtBenchmark.testStringBuilder ascii avgt 3 > 672.802 ┬▒ 29.740 ns/op > CharSequenceCharAtBenchmark.testStringBuilder non-ascii avgt 3 > 689.964 ┬▒ 791.175 ns/op > > jdk 25 > Benchmark (data) Mode Cnt > Score Error Units > CharSequenceCharAtBenchmark.testString ascii avgt 3 > 1176.057 ┬▒ 1157.979 ns/op > CharSequenceCharAtBenchmark.testString non-ascii avgt 3 > 697.382 ┬▒ 231.144 ns/op > CharSequenceCharAtBenchmark.testStringBuilder ascii avgt 3 > 692.970 ┬▒ 105.112 ns/op > CharSequenceCharAtBenchmark.testStringBuilder non-ascii avgt 3 > 703.178 ┬▒ 446.019 ns/op > > jdk 26 > Benchmark (data) Mode Cnt > Score Error Units > CharSequenceCharAtBenchmark.testString ascii avgt 3 > 1132.971 ┬▒ 350.786 ns/op > CharSequenceCharAtBenchmark.testString non-ascii avgt 3 > 688.201 ┬▒ 175.797 ns/op > CharSequenceCharAtBenchmark.testStringBuilder ascii avgt 3 > 704.380 ┬▒ 101.763 ns/op > CharSequenceCharAtBenchmark.testStringBuilder non-ascii avgt 3 > 673.622 ┬▒ 51.462 ns/op > > > @Warmup(iterations = 2, time = 7, timeUnit = TimeUnit.SECONDS) > @BenchmarkMode(Mode.AverageTime) > @OutputTimeUnit(TimeUnit.NANOSECONDS) > @State(Scope.Benchmark) > @Fork(value = 1, jvmArgsPrepend = {"-Xms512M", "-Xmx512M"}) > public class CharSequenceCharAtBenchmark { > > @Param(value = {"ascii", "non-ascii"}) > public String data; > > private String string; > > private StringBuilder stringBuilder; > > @Setup(Level.Trial) > public void setup() throws Exception { > StringBuilder sb = new StringBuilder(3152); > for (int i=0; i<3152; ++i) { > char c = (char) i; > if ("ascii".equals(data)) { > c = (char) (i & 0x7f); > } > sb.append(c); > } > > string = sb.toString(); > stringBuilder = sb; > } > > @Benchmark > public int testString() { > String sequence = this.string; > int sum = 0; > for (int i=0, j=sequence.length(); i<j; ++i) { > sum += sequence.charAt(i); > } > return sum; > } > > @Benchmark > public int testStringBuilder() { > StringBuilder sequence = this.stringBuilder; > int sum = 0; > for (int i=0, j=sequence.length(); i<j; ++i) { > sum += sequence.charAt(i); > } > return sum; > } > } > >