我最初编写此代码来检查将字符串放入缓冲区的最快方法,但很快发现了性能异常。
测试现在包含三个相关方法:'慢'' alpha'和' beta'。 ' alpha'的代码和' beta'是完全一样的。然后我测量用每种方法进行N次迭代所花费的时间,结果发现带有' beta'花费的时间比使用' alpha'的循环多2倍。似乎第3个循环总是比第二个循环慢2倍,即使我交换方法也是如此。
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
public class Main {
private static final int N = 1_000_000;
private static Field stringBytes;
private static String testString;
static {
// setup test string:
StringBuilder builder = new StringBuilder(1024);
for (int i = 0; i < 100; i++) {
builder.append("Hello, world!");
}
testString = builder.toString();
// setup String byte array field:
try {
Field stringValue = String.class.getDeclaredField("value");
stringValue.setAccessible(true);
stringBytes = stringValue;
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IllegalAccessException {
ByteBuffer expectedBuffer = ByteBuffer.allocate(2000)
.put(testString.getBytes());
ByteBuffer testBuffer = ByteBuffer.allocate(2000);
//
for (int i = 0; i < 10; i++) {
runTests(testBuffer, expectedBuffer);
}
}
private static void runTests(ByteBuffer testBuffer, ByteBuffer expectedBuffer) throws
IllegalAccessException {
long startTime = System.nanoTime();
for (int i = 0; i < N; i++) {
testBuffer.clear();
slow(testBuffer);
checkResult(testBuffer, expectedBuffer);
}
long endTime = System.nanoTime();
System.out.println("Slow: \t" + (endTime - startTime));
//
startTime = System.nanoTime();
for (int i = 0; i < N; i++) {
testBuffer.clear();
alpha(testBuffer);
checkResult(testBuffer, expectedBuffer);
}
endTime = System.nanoTime();
System.out.println("Alpha: \t" + (endTime - startTime));
//
startTime = System.nanoTime();
for (int i = 0; i < N; i++) {
testBuffer.clear();
beta(testBuffer);
checkResult(testBuffer, expectedBuffer);
}
endTime = System.nanoTime();
System.out.println("Beta: \t" + (endTime - startTime));
}
// make sure the JIT doesn't discard computations
private static void checkResult(ByteBuffer got, ByteBuffer expected) {
if (!got.equals(expected)) {
throw new RuntimeException(
String.format("expected: %s, got %s", expected, got)
);
}
}
private static void slow(ByteBuffer source) {
source.put(testString.getBytes());
}
private static void alpha(ByteBuffer source) throws IllegalAccessException {
source.put((byte[]) stringBytes.get(testString));
}
private static void beta(ByteBuffer source) throws IllegalAccessException {
source.put((byte[]) stringBytes.get(testString));
}
}
什么会导致如此剧烈的性能差异?如何在代码中避免这种差异?
这是运行程序时的输出(非法访问警告除外):
Slow: 4271284211
Alpha: 1089785263
Beta: 1067286082
Slow: 3772404211
Alpha: 1100012164
Beta: 1869625263
Slow: 3779312281
Alpha: 1261239766
Beta: 1949156491
Slow: 3778842573
Alpha: 1067640702
Beta: 1914821988
Slow: 3860709240
Alpha: 1084109473
Beta: 1878945497
Slow: 3662584328
Alpha: 1058276492
Beta: 1819476024
Slow: 3665676725
Alpha: 1061351111
Beta: 1855920467
Slow: 3725946199
Alpha: 1070417778
Beta: 1843628538
Slow: 3666171696
Alpha: 1062847251
Beta: 1829787135
Slow: 3663726784
Alpha: 1055333802
Beta: 1821107836
设置:x64 win10 java9