性能说明:使用未使用的变量,代码运行得更

ass*_*ias 15 java performance multithreading jvm

我之前做过一些性能测试,无法解释我获得的结果.

在运行下面的测试时,如果我取消注释private final List<String> list = new ArrayList<String>();,性能会显着提高.在我的机器上,测试在该字段存在时以70-90毫秒运行,而在注释掉时则为650毫秒.

我还注意到,如果我将print语句更改为System.out.println((end - start) / 1000000);,则没有变量的测试运行时间为450-500 ms而不是650 ms.变量存在时无效.

我的问题:

  1. 考虑到我甚至不使用那个变量,任何人都可以解释有或没有变量的近10个因子吗?
  2. 该打印语句如何改变性能(特别是性能测量窗口之后)?

ps:当顺序运行时,3个场景(带有变量,没有变量,带有不同的print语句)都需要大约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;
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

请参阅以下3个方案的10次运行结果:

  • 没有变量,使用短打印语句
  • 没有变量,使用long print语句(打印其中一个对象)
  • 顺序运行(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
Run Code Online (Sandbox Code Playgroud)

bes*_*sss 10

清除(错误)共享

由于内存中的布局,对象共享缓存行...已经解释了很多次(甚至在这个网站上):这里是进一步阅读的好资料.问题是适用于C#一样多(或C/C++)

当您通过添加注释掉的行来填充对象时,共享会更少,并且您会看到性能提升.

编辑:我错过了第二个问题:


该打印语句如何改变性能(特别是在性能测量窗口之后)?

我觉得没有足够的变暖,打印GC和编译日志,这样你就可以确定没有干扰,代码实际上是编译的. java -server需要10k次迭代,最好不要在主循环中全部生成良好的代码.