<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    Hi Brett,<br>
    <br>
    I'd suggest separate initialization and test methods for the two
    cases to get more reliable numbers.<br>
    <br>
    By using @Trial and using a common field for the test data, I think
    you have handicapped C2.<br>
    The training runs JMH does to warm up C2 are 'seeing' two different
    types for the value of sequence.<br>
    Making the test runs independent will remov doubt about interactions
    due to the test setup.<br>
    <br>
    Roger<br>
    <br>
    <div class="moz-cite-prefix">On 7/21/25 1:43 PM, Brett Okken wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CANBJVOHbJxR9TCLW4OWuN2uMP4TN-ZKhJTvOwZeUvXYQOv0j6g@mail.gmail.com">
      
      <div dir="ltr">
        <div>> 
          output labeled as StringBuffer but the jmh creates
          StringBuilder.<br>
        </div>
        <div><br>
        </div>
        <div>Ugh - sorry about that. But yes - this is about
          StringBuilder vs String.</div>
        <div><br>
        </div>
        <div>> I would not be surprised that C2 has more
          optimizations for String than for StringBuilder.</div>
        <div><br>
        </div>
        <div>If that were true, it would not surprise me. However, these
          tests show the opposite. String is /slower/ than
          StringBuilder.</div>
      </div>
      <br>
      <div class="gmail_quote gmail_quote_container">
        <div dir="ltr" class="gmail_attr">On Mon, Jul 21, 2025 at
          12:34 PM Roger Riggs <<a href="mailto:roger.riggs@oracle.com" moz-do-not-send="true" class="moz-txt-link-freetext">roger.riggs@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> Hi Brett,<br>
            <br>
            The labeling of the output is confusing, the test output
            labeled as StringBuffer but the jmh creates StringBuilder.<br>
            (StringBuffer methods are all synchronized and could explain
            why they are slower).<br>
            <br>
            Also, I would not be surprised that C2 has more
            optimizations for String than for StringBuilder.<br>
            <br>
            Regards, Roger<br>
            <br>
            <div>On 7/19/25 6:09 PM, Brett Okken wrote:<br>
            </div>
            <blockquote type="cite">
              <div dir="ltr">Making sequence a local variable does
                improve things (especially for ascii), but a substantial
                difference remains. It appears that the performance
                difference for ascii goes all the way back to jdk 11.
                The difference for non-ascii showed up in jdk 21. I
                wonder if this is related to the index checks?<br>
                <br>
                <span style="font-family:monospace">jdk 11<br>
                  <br>
                  Benchmark  (data)      (source)  Mode  Cnt     Score  
                     Error  Units<br>
                  test        ascii        String  avgt    3  1137.348 ±
                    12.835  ns/op<br>
                  test        ascii  StringBuffer  avgt    3   712.874 ±
                   509.320  ns/op<br>
                  test    non-ascii        String  avgt    3   668.657 ±
                   246.550  ns/op<br>
                  test    non-ascii  StringBuffer  avgt    3   897.344 ±
                  4353.414  ns/op<br>
                  <br>
                  <br>
                  jdk 17<br>
                  Benchmark  (data)      (source)  Mode  Cnt     Score  
                     Error  Units<br>
                  test        ascii        String  avgt    3  1321.497 ±
                  2107.466  ns/op<br>
                  test        ascii  StringBuffer  avgt    3   715.936 ±
                   412.189  ns/op<br>
                  test    non-ascii        String  avgt    3   722.986 ±
                   443.389  ns/op<br>
                  test    non-ascii  StringBuffer  avgt    3   722.787 ±
                   771.816  ns/op</span><span style="font-family:monospace"><br>
                  <br>
                  <br>
                  jdk 21<br>
                  Benchmark  (data)      (source)  Mode  Cnt     Score  
                      Error  Units<br>
                  test        ascii        String  avgt    3  1150.301
                  ┬▒   918.549  ns/op<br>
                  test        ascii  StringBuffer  avgt    3   713.183
                  ┬▒   543.850  ns/op<br>
                  test    non-ascii        String  avgt    3  4642.667
                  ┬▒ 11481.029  ns/op<br>
                  test    non-ascii  StringBuffer  avgt    3   728.027
                  ┬▒   936.521  ns/op<br>
                  <br>
                  <br>
                  jdk 25<br>
                  Benchmark  (data)      (source)  Mode  Cnt     Score  
                     Error  Units<br>
                  test        ascii        String  avgt    3  1184.513
                  ┬▒ 2057.498  ns/op<br>
                  test        ascii  StringBuffer  avgt    3   786.611
                  ┬▒  411.657  ns/op<br>
                  test    non-ascii        String  avgt    3  4197.585
                  ┬▒ 2761.388  ns/op<br>
                  test    non-ascii  StringBuffer  avgt    3   716.375
                  ┬▒  815.349  ns/op<br>
                  <br>
                  <br>
                  jdk 26<br>
                  Benchmark  (data)      (source)  Mode  Cnt     Score  
                    Error  Units<br>
                  test        ascii        String  avgt    3  1107.207
                  ┬▒ 423.072  ns/op<br>
                  test        ascii  StringBuffer  avgt    3   742.780
                  ┬▒ 178.890  ns/op<br>
                  test    non-ascii        String  avgt    3  4043.914
                  ┬▒ 498.439  ns/op<br>
                  test    non-ascii  StringBuffer  avgt    3   712.535
                  ┬▒ 583.255  ns/op</span><br>
              </div>
              <br>
              <br>
              <div class="gmail_quote">
                <div dir="ltr" class="gmail_attr">On Sat, Jul 19, 2025
                  at 4:17 PM Chen Liang <<a href="mailto:liangchenblue@gmail.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">liangchenblue@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">
                    <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">
                      <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" target="_blank" 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">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>
                </blockquote>
              </div>
            </blockquote>
            <br>
          </div>
        </blockquote>
      </div>
    </blockquote>
    <br>
  </body>
</html>