Как JVM мешает «оптимизировать все» в этом примере кода из Effective Java? - PullRequest
0 голосов
/ 08 декабря 2018

Я нашел этот пример кода для книги Джошуа Блоха "Эффективная Java".Он предназначен для демонстрации того, почему вы должны избегать ненужного создания объектов:

public class Sum {
    private static long sum() {
        Long sum = 0L;
        for (long i = 0; i <= Integer.MAX_VALUE; i++)
            sum += i;
        return sum;
    }

    public static void main(String[] args) {
        int numSets = Integer.parseInt(args[0]);
        long x = 0;

        for (int i = 0; i < numSets; i++) {
            long start = System.nanoTime();
            x += sum();
            long end = System.nanoTime();
            System.out.println((end - start) / 1_000_000. + " ms.");
        }

        // Prevents VM from optimizing away everything.
        if (x == 42)
            System.out.println();
    }
}

Что здесь выполняют две последние строки основного метода?

Ответы [ 3 ]

0 голосов
/ 08 декабря 2018

Это окончательное сравнение является единственным использованием этой переменной.Без этого кого бы волновало значение этой переменной?

Никто!

Итак, компилятор может предположить: это значение никогда не используется, и код, который записывает в него, имеет побочные эффекты узла.Вещи, которые не привыкают, зачем тратить время на их написание.

Таким образом: последнее окончательное использование «read» предотвращает чрезмерную готовность компилятора «оптимизировать» вызов метода, который вы намерены измерять!

0 голосов
/ 08 декабря 2018

Две последние строки будут обеспечивать, чтобы JVM не удаляла вызовы, которые она могла бы потенциально рассматривать как отсутствие операций, иначе, один из вариантов - использовать результат - так что вы можете суммировать все возвращаемые значения и затем отобразить сумму вконец.

Другой способ предотвратить оптимизацию vm - отключить JIT:

-Djava.compiler=NONE

JIT:

Когда JVM компилирует файл класса, он нене завершите полный файл класса;он компилирует только часть этого по мере необходимости.Это позволяет избежать тяжелого разбора всего исходного кода.Этот тип компиляции называется компиляцией JIT или Just-In-Time.JVM зависит от платформы (ОС). Генерация кода JIT ориентирована на платформу, генерирует собственный байтовый код, поэтому он быстрее, чем JVM:)

0 голосов
/ 08 декабря 2018

Последние две строки заставляют компилятор выполнить весь цикл, чтобы найти значение x.В противном случае он может обнаружить, что x вообще не используется, и проигнорировать цикл, учитывая, что внутри него не выполняется "настоящая" работа.Даже если sum() вызывается неоднократно, результат накопления возвращаемого значения в конце будет отброшен, если мы ничего не сделаем с x.

Конечно, это предполагает, что оператор println() внутрицикл может быть безопасно проигнорирован, я не уверен, что компилятор может принять такое решение.Это был бы один агрессивный компилятор!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...