<div dir="ltr"><div dir="ltr">Without looking at C2 IRs, I think there are a few potential culprits we can look into:</div><div>1. JDK-8351000 and JDK-8351443 updated StringBuilder</div><div>2. Sequence field is read in the loop; I wonder if making it an explicit immutable local variable changes anything here.</div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Sat, Jul 19, 2025 at 2:34 PM Brett Okken <<a href="mailto:brett.okken.os@gmail.com">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">I was looking at the performance of StringCharBuffer for various<br>
backing CharSequence types and was surprised to see a significant<br>
performance difference between String and StringBuffer. I wrote a<br>
small jmh which shows that the String implementation of charAt is<br>
significantly slower than StringBuilder. Is this expected?<br>
<br>
Benchmark (data) (source) Mode Cnt<br>
Score Error Units<br>
CharSequenceCharAtBenchmark.test ascii String avgt 3<br>
2537.311 ┬▒ 8952.197 ns/op<br>
CharSequenceCharAtBenchmark.test ascii StringBuffer avgt 3<br>
852.004 ┬▒ 2532.958 ns/op<br>
CharSequenceCharAtBenchmark.test non-ascii String avgt 3<br>
5115.381 ┬▒ 13822.592 ns/op<br>
CharSequenceCharAtBenchmark.test non-ascii StringBuffer avgt 3<br>
836.230 ┬▒ 1154.191 ns/op<br>
<br>
<br>
<br>
@Measurement(iterations = 3, time = 5, timeUnit = TimeUnit.SECONDS)<br>
@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>
@Param(value = {"String", "StringBuffer"})<br>
public String source;<br>
<br>
private CharSequence sequence;<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>
switch(source) {<br>
case "String":<br>
sequence = sb.toString();<br>
break;<br>
case "StringBuffer":<br>
sequence = sb;<br>
break;<br>
default:<br>
throw new IllegalArgumentException(source);<br>
}<br>
}<br>
<br>
@Benchmark<br>
public int test() {<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>
</blockquote></div></div>