<div dir="ltr">I am running Windows x64. Windows 11 Pro 24H2<br><br>Intel(R) Core(TM) i7-1370P</div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Mon, Jul 21, 2025 at 4:59 PM Chen Liang <<a href="mailto:chen.l.liang@oracle.com">chen.l.liang@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="msg-980570505404957663">
<div dir="ltr">
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
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.</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
This is the results I've got:</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
Benchmark (data) Mode Cnt Score Error Units</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
CharSequenceCharAtBenchmark.testString ascii avgt 5 668.649 ± 13.895 ns/op</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
CharSequenceCharAtBenchmark.testString non-ascii avgt 5 651.903 ± 7.240 ns/op</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
CharSequenceCharAtBenchmark.testStringBuilder ascii avgt 5 673.802 ± 26.260 ns/op</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
CharSequenceCharAtBenchmark.testStringBuilder non-ascii avgt 5 657.374 ± 35.785 ns/op</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
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.</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:"Calibri Light","Helvetica Light",sans-serif;font-size:12pt;color:rgb(0,0,0)">
Chen</div>
<div id="m_-1513961703257390956appendonsend"></div>
<hr style="display:inline-block;width:98%">
<div id="m_-1513961703257390956divRplyFwdMsg">
<div style="direction:ltr;font-family:Calibri,sans-serif;font-size:11pt;color:rgb(0,0,0)">
<b>From:</b> core-libs-dev <<a href="mailto:core-libs-dev-retn@openjdk.org" target="_blank">core-libs-dev-retn@openjdk.org</a>> on behalf of Brett Okken <<a href="mailto:brett.okken.os@gmail.com" target="_blank">brett.okken.os@gmail.com</a>><br>
<b>Sent:</b> Monday, July 21, 2025 4:01 PM<br>
<b>To:</b> Roger Riggs <<a href="mailto:roger.riggs@oracle.com" target="_blank">roger.riggs@oracle.com</a>><br>
<b>Cc:</b> <a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> Re: String.charAt vs StringBuilder.charAt performance</div>
<div style="direction:ltr"> </div>
</div>
<div style="direction:ltr">Updating to have different test methods for each representation did remove the difference for the non-ascii String case for the jdk 21+ releases.</div>
<div style="direction:ltr">However, the ascii (latin) strings are still slower with String than StringBuilder.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">How does C2 then handle something like StringCharBuffer wrapping a CharSequence for all of it's get operations:<br>
<a id="m_-1513961703257390956OWA40ec9115-eaed-2ada-80c0-c15e0af7747e" href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/StringCharBuffer.java#L88-L97" target="_blank">https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/StringCharBuffer.java#L88-L97</a></div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Which is then used by CharBufferSpliterator<br>
<a id="m_-1513961703257390956OWAacbd9ce8-343b-afef-5378-9e449ad9045b" href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/CharBufferSpliterator.java" target="_blank">https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/CharBufferSpliterator.java</a></div>
<div style="direction:ltr"><br>
And by many CharsetEncoder impls when either source or destination is not backed by array (which would be the case if StringCharBuffer used):<br>
<a id="m_-1513961703257390956OWA68f87162-b4e6-37b4-4cf4-3103668591c4" href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/sun/nio/cs/UTF_8.java#L517" target="_blank">https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/sun/nio/cs/UTF_8.java#L517</a></div>
<div style="direction:ltr"><a id="m_-1513961703257390956OWA7cef33e8-fc21-cd8e-3e0b-e818d65dc943" href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/sun/nio/cs/UnicodeEncoder.java#L81" target="_blank">https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/sun/nio/cs/UnicodeEncoder.java#L81</a></div>
<div style="direction:ltr;font-family:monospace"><br>
</div>
<div style="direction:ltr;font-family:monospace"><br>
</div>
<div style="direction:ltr;font-family:monospace"><br>
</div>
<div style="direction:ltr;font-family:monospace">jdk 17<br>
Benchmark (data) Mode Cnt Score Error Units<br>
CharSequenceCharAtBenchmark.testString ascii avgt 3 1429.358 ± 623.424 ns/op<br>
CharSequenceCharAtBenchmark.testString non-ascii avgt 3 705.282 ± 233.453 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder ascii avgt 3 724.138 ± 267.346 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder non-ascii avgt 3 718.357 ± 864.066 ns/op<br>
<br>
jdk 21<br>
Benchmark (data) Mode Cnt Score Error Units<br>
CharSequenceCharAtBenchmark.testString ascii avgt 3 1087.024 ┬▒ 235.082 ns/op<br>
CharSequenceCharAtBenchmark.testString non-ascii avgt 3 687.520 ┬▒ 747.532 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder ascii avgt 3 672.802 ┬▒ 29.740 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder non-ascii avgt 3 689.964 ┬▒ 791.175 ns/op<br>
<br>
jdk 25<br>
Benchmark (data) Mode Cnt Score Error Units<br>
CharSequenceCharAtBenchmark.testString ascii avgt 3 1176.057 ┬▒ 1157.979 ns/op<br>
CharSequenceCharAtBenchmark.testString non-ascii avgt 3 697.382 ┬▒ 231.144 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder ascii avgt 3 692.970 ┬▒ 105.112 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder non-ascii avgt 3 703.178 ┬▒ 446.019 ns/op<br>
<br>
jdk 26<br>
Benchmark (data) Mode Cnt Score Error Units<br>
CharSequenceCharAtBenchmark.testString ascii avgt 3 1132.971 ┬▒ 350.786 ns/op<br>
CharSequenceCharAtBenchmark.testString non-ascii avgt 3 688.201 ┬▒ 175.797 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder ascii avgt 3 704.380 ┬▒ 101.763 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder non-ascii avgt 3 673.622 ┬▒ 51.462 ns/op</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr;font-family:monospace">@Warmup(iterations = 2, time = 7, timeUnit = TimeUnit.SECONDS)<br>
@BenchmarkMode(Mode.AverageTime)<br>
@OutputTimeUnit(TimeUnit.NANOSECONDS)<br>
@State(Scope.Benchmark)<br>
@Fork(value = 1, jvmArgsPrepend = {"-Xms512M", "-Xmx512M"})<br>
public class CharSequenceCharAtBenchmark {<br>
<br>
@Param(value = {"ascii", "non-ascii"})<br>
public String data;<br>
<br>
private String string;<br>
<br>
private StringBuilder stringBuilder;<br>
<br>
@Setup(Level.Trial)<br>
public void setup() throws Exception {<br>
StringBuilder sb = new StringBuilder(3152);<br>
for (int i=0; i<3152; ++i) {<br>
char c = (char) i;<br>
if ("ascii".equals(data)) {<br>
c = (char) (i & 0x7f);<br>
}<br>
sb.append(c);<br>
}<br>
<br>
string = sb.toString();<br>
stringBuilder = sb;<br>
}<br>
<br>
@Benchmark<br>
public int testString() {<br>
String sequence = this.string;<br>
int sum = 0;<br>
for (int i=0, j=sequence.length(); i<j; ++i) {<br>
sum += sequence.charAt(i);<br>
}<br>
return sum;<br>
}<br>
<br>
@Benchmark<br>
public int testStringBuilder() {<br>
StringBuilder sequence = this.stringBuilder;<br>
int sum = 0;<br>
for (int i=0, j=sequence.length(); i<j; ++i) {<br>
sum += sequence.charAt(i);<br>
}<br>
return sum;<br>
}<br>
}</div>
<div><br>
</div>
</div>
</div></blockquote></div>