<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ks_c_5601-1987">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: "Calibri Light", "Helvetica Light", sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
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);" class="elementToProof">
<br>
</div>
<div style="font-family: "Calibri Light", "Helvetica Light", sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
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);" class="elementToProof">
<br>
</div>
<div style="font-family: "Calibri Light", "Helvetica Light", sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
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);" class="elementToProof">
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);" class="elementToProof">
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);" class="elementToProof">
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);" class="elementToProof">
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);" class="elementToProof">
<br>
</div>
<div style="font-family: "Calibri Light", "Helvetica Light", sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
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);" class="elementToProof">
<br>
</div>
<div style="font-family: "Calibri Light", "Helvetica Light", sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Chen</div>
<div class="elementToProof" id="appendonsend"></div>
<hr style="display: inline-block; width: 98%;">
<div class="elementToProof" id="divRplyFwdMsg">
<div style="direction: ltr; font-family: Calibri, sans-serif; font-size: 11pt; color: rgb(0, 0, 0);" class="elementToProof">
<b>From:</b> core-libs-dev <core-libs-dev-retn@openjdk.org> on behalf of Brett Okken <brett.okken.os@gmail.com><br>
<b>Sent:</b> Monday, July 21, 2025 4:01 PM<br>
<b>To:</b> Roger Riggs <roger.riggs@oracle.com><br>
<b>Cc:</b> core-libs-dev@openjdk.org <core-libs-dev@openjdk.org><br>
<b>Subject:</b> Re: String.charAt vs StringBuilder.charAt performance</div>
<div style="direction: ltr;" class="elementToProof"> </div>
</div>
<div style="direction: ltr;" class="elementToProof">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;" class="elementToProof">However, the ascii (latin) strings are still slower with String than StringBuilder.</div>
<div style="direction: ltr;" class="elementToProof"><br>
</div>
<div style="direction: ltr;" class="elementToProof">How does C2 then handle something like StringCharBuffer wrapping a CharSequence for all of it's get operations:<br>
<a data-auth="NotApplicable" class="OWAAutoLink" id="OWA40ec9115-eaed-2ada-80c0-c15e0af7747e" href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/StringCharBuffer.java#L88-L97">https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/StringCharBuffer.java#L88-L97</a></div>
<div style="direction: ltr;" class="elementToProof"><br>
</div>
<div style="direction: ltr;" class="elementToProof">Which is then used by CharBufferSpliterator<br>
<a data-auth="NotApplicable" class="OWAAutoLink" id="OWAacbd9ce8-343b-afef-5378-9e449ad9045b" href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/CharBufferSpliterator.java">https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/CharBufferSpliterator.java</a></div>
<div style="direction: ltr;" class="elementToProof"><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 data-auth="NotApplicable" class="OWAAutoLink" id="OWA68f87162-b4e6-37b4-4cf4-3103668591c4" href="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/UTF_8.java#L517</a></div>
<div style="direction: ltr;" class="elementToProof"><a data-auth="NotApplicable" class="OWAAutoLink" id="OWA7cef33e8-fc21-cd8e-3e0b-e818d65dc943" href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/sun/nio/cs/UnicodeEncoder.java#L81">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;" class="elementToProof"><br>
</div>
<div style="direction: ltr; font-family: monospace;" class="elementToProof"><br>
</div>
<div style="direction: ltr; font-family: monospace;" class="elementToProof"><br>
</div>
<div style="direction: ltr; font-family: monospace;" class="elementToProof">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;" class="elementToProof"><br>
</div>
<div style="direction: ltr;" class="elementToProof"><br>
</div>
<div style="direction: ltr; font-family: monospace;" class="elementToProof">@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 class="elementToProof"><br>
</div>
</body>
</html>