Объяснение производительности :код работает быстрее с неиспользуемой переменной

Ранее я проводил некоторые тесты производительности и не могу объяснить полученные результаты.

При выполнении приведенного ниже теста, если я раскомментирую private final List<String> list = new ArrayList<String>();, производительность значительно улучшится. На моей машине тест выполняется за 70 -90 мс, когда это поле присутствует, и за 650 мс, когда оно закомментировано.

Я также заметил, что если я изменю оператор печати на System.out.println((end - start) / 1000000);, тест без переменной выполняется за 450 -500 мс вместо 650 мс. Это не имеет никакого эффекта, когда переменная присутствует.

Мои вопросы:

  1. Может ли кто-нибудь объяснить коэффициент почти 10 с переменной или без нее, учитывая, что я даже не использую эту переменную?
  2. Как этот оператор печати может изменить производительность (, тем более, что он идет после окна измерения производительности )?

ps :при последовательном запуске 3 сценария (с переменной, без переменной, с другим оператором печати )занимают около 260 мс.

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
15
задан assylias 20 August 2012 в 15:38
поделиться