<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div class="moz-cite-prefix">Hi Brett,<br>
<br>
I ran your benchmark on a Windows11 Pro 24H2 / ARM64 / JDK 21
system and can reproduce your findings that
CharSequenceCharAtBenchmark.testString<ascii> has weaker
performance.<br>
I also added these benchmarks:<br>
<font face="monospace"> @Benchmark<br>
public int testStringBuilderAsCS() {<br>
return test(this.stringBuilder);<br>
}<br>
<br>
@Benchmark<br>
public int testStringAsCS() {<br>
return test(this.string);<br>
}<br>
<br>
private int test(CharSequence sequence) {<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>
}</font><br>
<br>
and see a total breakdown of
CharSequenceCharAtBenchmark.testStringAsCS<br>
<br>
<font face="monospace">Benchmark
(data) Mode Cnt Score Error Units<br>
CharSequenceCharAtBenchmark.testString ascii
avgt 5 1647,439 ± 70,486 ns/op<br>
CharSequenceCharAtBenchmark.testString non-ascii
avgt 5 939,780 ± 63,896 ns/op<br>
CharSequenceCharAtBenchmark.testStringAsCS ascii
avgt 5 1657,796 ± 18,488 ns/op<br>
CharSequenceCharAtBenchmark.testStringAsCS non-ascii
avgt 5 9400,447 ± 290,066 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder ascii
avgt 5 923,943 ± 6,130 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder non-ascii
avgt 5 941,507 ± 30,786 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilderAsCS ascii
avgt 5 930,974 ± 33,187 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilderAsCS non-ascii
avgt 5 945,983 ± 87,636 ns/op</font><br>
<br>
Best<br>
Johannes<br>
<br>
On 22/07/2025 13:44, Brett Okken wrote:<br>
</div>
<blockquote type="cite"
cite="mid:CANBJVOHC0533A7JMhckoDJ1X2SJQDbS=cccCpTECaSmAQzc3xQ@mail.gmail.com">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<div dir="ltr">It does look like this is windows specific. If I
run on WSL, I get results similar to your linux-x64:<br>
<br>
<span style="font-family:monospace">Benchmark
(data) Mode Cnt Score Error
Units<br>
CharSequenceCharAtBenchmark.testString ascii avgt
3 679.294 ± 302.947 ns/op<br>
CharSequenceCharAtBenchmark.testString non-ascii avgt
3 702.071 ± 926.959 ns/op<br>
CharSequenceCharAtBenchmark.testStringBuilder ascii avgt
3 682.815 ± 301.649 ns/op<br>
</span>
<div><span style="font-family:monospace">CharSequenceCharAtBenchmark.testStringBuilder
non-ascii avgt 3 678.169 ± 810.276 ns/op</span></div>
<div><span style="font-family:monospace"><br>
</span></div>
<div><font face="arial,sans-serif">And I go back to the original
version of the test, where String vs StringBuilder is
defined by parameter and both assigned to same local
variable as part of set up, that also shows no difference in
wsl.</font></div>
<div><font face="arial,sans-serif">So it appears everything I
observed is an artifact of Windows specific intrinsics?</font></div>
<div><br>
</div>
<div><span style="font-family:monospace">Benchmark
(data) (source) Mode Cnt Score
Error Units<br>
CharSequenceCharAtBenchmark.test ascii String
avgt 3 660.597 ± 146.405 ns/op<br>
CharSequenceCharAtBenchmark.test ascii StringBuilder
avgt 3 659.395 ± 155.167 ns/op<br>
CharSequenceCharAtBenchmark.test non-ascii String
avgt 3 647.955 ± 189.747 ns/op<br>
CharSequenceCharAtBenchmark.test non-ascii StringBuilder
avgt 3 639.678 ± 146.923 ns/op</span></div>
</div>
<br>
<div class="gmail_quote gmail_quote_container">
<div dir="ltr" class="gmail_attr">On Mon, Jul 21, 2025 at
5:13 PM Brett Okken <<a
href="mailto:brett.okken.os@gmail.com"
moz-do-not-send="true" class="moz-txt-link-freetext">brett.okken.os@gmail.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 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">
<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" target="_blank"
moz-do-not-send="true" class="moz-txt-link-freetext">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>
<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>
<hr style="display:inline-block;width:98%">
<div
id="m_-4906021454736115386m_-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" moz-do-not-send="true"
class="moz-txt-link-freetext">core-libs-dev-retn@openjdk.org</a>>
on behalf of Brett Okken <<a
href="mailto:brett.okken.os@gmail.com"
target="_blank" moz-do-not-send="true"
class="moz-txt-link-freetext">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" moz-do-not-send="true"
class="moz-txt-link-freetext">roger.riggs@oracle.com</a>><br>
<b>Cc:</b> <a
href="mailto:core-libs-dev@openjdk.org"
target="_blank" moz-do-not-send="true"
class="moz-txt-link-freetext">core-libs-dev@openjdk.org</a>
<<a href="mailto:core-libs-dev@openjdk.org"
target="_blank" moz-do-not-send="true"
class="moz-txt-link-freetext">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_-4906021454736115386m_-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" moz-do-not-send="true"
class="moz-txt-link-freetext">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_-4906021454736115386m_-1513961703257390956OWAacbd9ce8-343b-afef-5378-9e449ad9045b"
href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/CharBufferSpliterator.java"
target="_blank" moz-do-not-send="true"
class="moz-txt-link-freetext">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_-4906021454736115386m_-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" moz-do-not-send="true"
class="moz-txt-link-freetext">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_-4906021454736115386m_-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" moz-do-not-send="true"
class="moz-txt-link-freetext">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>
</blockquote>
</div>
</blockquote>
<br>
</body>
</html>