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