当您多次重复同一任务时,您的 CPU 往往会非常高效地运行。这是因为您的缓存未命中时间和 CPU 的预热不会成为一个因素。您也可能没有考虑您的 JVM 预热时间。
如果您在 JVM 和/或 CPU 未预热时尝试相同的操作。你会得到非常不同的结果。
尝试在测试之间做同样的事情说 25 次(小于你的编译阈值)和 sleep(100)。您应该期望看到更高的时间,更接近您在实际应用程序中看到的时间。
您的应用程序的行为会有所不同,但为了说明我的观点。我发现等待 IO 可能比普通睡眠更具破坏性。
当你执行你的基准测试时,你应该尽量确保你是在与同类进行比较。
import java.io.*;
import java.util.Date;
/**
Cold JVM with a Hot CPU took 123 us average
Cold JVM with a Cold CPU took 403 us average
Cold JVM with a Hot CPU took 314 us average
Cold JVM with a Cold CPU took 510 us average
Cold JVM with a Hot CPU took 316 us average
Cold JVM with a Cold CPU took 514 us average
Cold JVM with a Hot CPU took 315 us average
Cold JVM with a Cold CPU took 545 us average
Cold JVM with a Hot CPU took 321 us average
Cold JVM with a Cold CPU took 542 us average
Hot JVM with a Hot CPU took 44 us average
Hot JVM with a Cold CPU took 111 us average
Hot JVM with a Hot CPU took 32 us average
Hot JVM with a Cold CPU took 96 us average
Hot JVM with a Hot CPU took 26 us average
Hot JVM with a Cold CPU took 80 us average
Hot JVM with a Hot CPU took 26 us average
Hot JVM with a Cold CPU took 90 us average
Hot JVM with a Hot CPU took 25 us average
Hot JVM with a Cold CPU took 98 us average
*/
public class HotColdBenchmark {
public static void main(String... args) {
// load all the classes.
performTest(null, 25, false);
for (int i = 0; i < 5; i++) {
// still pretty cold
performTest("Cold JVM with a Hot CPU", 25, false);
// still pretty cold
performTest("Cold JVM with a Cold CPU", 25, true);
}
// warmup the JVM
performTest(null, 10000, false);
for (int i = 0; i < 5; i++) {
// warmed up.
performTest("Hot JVM with a Hot CPU", 25, false);
// bit cold
performTest("Hot JVM with a Cold CPU", 25, true);
}
}
public static long performTest(String report, int n, boolean sleep) {
long time = 0;
long ret = 0;
for (int i = 0; i < n; i++) {
long start = System.nanoTime();
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(new Date());
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Date d = (Date) ois.readObject();
ret += d.getTime();
time += System.nanoTime() - start;
if (sleep) Thread.sleep(100);
} catch (Exception e) {
throw new AssertionError(e);
}
}
if (report != null) {
System.out.printf("%s took %,d us average%n", report, time / n / 1000);
}
return ret;
}
}