【发布时间】:2012-08-04 14:34:25
【问题描述】:
我之前做了一些性能测试,无法解释我得到的结果。
运行下面的测试时,如果我取消注释private final List<String> list = new ArrayList<String>();,性能会显着提高。在我的机器上,当该字段存在时,测试在 70-90 毫秒内运行,而当它被注释掉时,测试运行时间为 650 毫秒。
我还注意到,如果我将打印语句更改为System.out.println((end - start) / 1000000);,没有变量的测试将在 450-500 毫秒而不是 650 毫秒内运行。变量存在时无效。
我的问题:
- 考虑到我什至不使用该变量,任何人都可以解释几乎 10 的因子有或没有变量吗?
- 该打印语句如何改变性能(尤其是因为它在性能测量窗口之后)?
ps:顺序运行时,3个场景(有变量,无变量,打印语句不同)都需要260ms左右。
public class SOTest {
private static final int ITERATIONS = 10000000;
private static final int THREADS = 4;
private volatile long id = 0L;
//private final List<String> list = new ArrayList<String>();
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(THREADS);
final List<SOTest> objects = new ArrayList<SOTest>();
for (int i = 0; i < THREADS; i++) {
objects.add(new SOTest());
}
//warm up
for (SOTest t : objects) {
getRunnable(t).run();
}
long start = System.nanoTime();
for (SOTest t : objects) {
executor.submit(getRunnable(t));
}
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
long end = System.nanoTime();
System.out.println(objects.get(0).id + " " + (end - start) / 1000000);
}
public static Runnable getRunnable(final SOTest object) {
Runnable r = new Runnable() {
@Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
object.id++;
}
}
};
return r;
}
}
编辑
请看下面 10 次运行 3 种场景的结果:
- 没有变量,使用简短的打印语句
- 不带变量,使用长打印语句(打印其中一个对象)
- 顺序运行(1 个线程)
- 带变量
1 657 473 261 74
2 641 501 261 78
3 651 465 259 86
4 585 462 259 78
5 639 506 259 68
6 659 477 258 72
7 653 479 259 82
8 645 486 259 72
9 650 457 259 78
10 639 487 272 79
【问题讨论】:
-
您多久重复一次测试?这些时间是平均值吗?
-
@Baz 是的,这些是几次运行的平均值(比如 10-15 次运行),从一次运行到另一次运行结果相当稳定。
-
你statistically prove确实不一样吗?可能只是“随机性”产生的噪音。如果你不这样做,我会首先尝试重复实验并收集足够大的样本来对数据进行统计声明。这并不费力,并且可以防止很多头痛(在其他情况下,如果不在此处)。
-
您是否一遍又一遍地测试,没有暂停或清理过程?它只是让一切变得不同!
-
我注意到
private final List<String> list = new ArrayList<String>();可以替换为{System.out.println("wtf");}哈哈
标签: java multithreading performance jvm