String.charAt性能下降一倍

有朋友发现对于下面的test程序

import java.util.concurrent.TimeUnit;
import java.util.Random;

public class Test {

  private final int TEST_STRING_LENGTH = 1024 * 64;
  private String testString;
  private byte[] bytes = new byte[TEST_STRING_LENGTH * 3];
  
  private void generateRandomString() {
    StringBuilder sb = new StringBuilder();
    Random random = new Random();
    for (int i = 0; i < TEST_STRING_LENGTH; i++) {
      sb.append((char) (random.nextInt(26) + 'A'));
    }
    testString = sb.toString();
  }

  private static int encodeUTF8(String str, byte[] bytes) {
    int offset = 0;
    int len = str.length();
    int sl = offset + len;
    int dp = 0;
    int dlASCII = dp + Math.min(len, bytes.length);

    // ASCII only optimized loop
    while (dp < dlASCII && str.charAt(offset) < '\u0080') {
      bytes[dp++] = (byte) str.charAt(offset++);
    }
    return dp;
  }

  public static void main(String[] args) {
    Test t = new Test();
    t.generateRandomString();
    for (int i = 0; i < 200000; i++) {
      encodeUTF8(t.testString, t.bytes);
    }
  }
}

JDK-8268698之后这段代码慢了一倍:

Before JDK-8268698,
    real 0m8.369s
    user 0m8.386s
    sys 0m0.019s

After JDK-8268698,
    real 0m19.722s
    user 0m19.748s
    sys 0m0.013s

检查实现发现是str.charAt性能下降导致的。

class String{
   public char charAt(int index) {
       if (isLatin1()) {
           return StringLatin1.charAt(value, index);
       } else {
           return StringUTF16.charAt(value, index);
       }
   }
}
final class StringLatin1 {
   public static char charAt(byte[] value, int index) {
       checkIndex(index, value.length, null);
       return (char)(value[index] & 0xff);
   }
}

image

PR: https://github.com/openjdk/jdk/pull/6096

原文地址:https://www.cnblogs.com/kelthuzadx/p/15726427.html