Оптимизация компилятора Java для повторных вызовов методов? - PullRequest
7 голосов
/ 02 августа 2010

Оптимизирует ли java-компилятор (javac по умолчанию, который входит в JDK1.6.0_21) код, чтобы снова и снова вызывать один и тот же метод с одинаковыми аргументами? Если бы я написал этот код:

public class FooBar {
    public static void main(String[] args) {
        foo(bar);
        foo(bar);
        foo(bar);
    }
}

Будет ли метод foo(bar) запускаться только один раз? Если так, есть ли способ предотвратить эту оптимизацию? (Я пытаюсь сравнить время выполнения для двух алгоритмов, одного итеративного и одного сравнительного, и я хочу назвать их несколько раз, чтобы получить репрезентативную выборку)

Любое понимание будет высоко ценится; Я довел эту проблему до безумия (хотя мой компьютер некоторое время работал безумно быстро, поэтому я продолжал добавлять вызовы методов, пока не получил ошибку code too large в 43671 строке).

Ответы [ 4 ]

6 голосов
/ 02 августа 2010

Оптимизация, которую вы наблюдаете, вероятно, не имеет ничего общего с повторными вызовами ... потому что это была бы недопустимая оптимизация. Скорее всего, оптимизатор выяснил, что вызовы методов не оказывают заметного влияния на вычисления.

Лекарство заключается в том, чтобы изменить метод, чтобы он влиял на результат вычислений ...

4 голосов
/ 02 августа 2010

Это не так;это может вызвать большую проблему, если foo не является чистым (изменяет глобальное состояние программы).Например:

public class FooBar {
    private int i = 0;
    private static int foo() {
        return ++i;
    }

    public static void main(String[] args) {
        foo();
        foo();
        foo();
        System.out.println(i);
    }
}
3 голосов
/ 02 августа 2010

Вы не предоставили достаточно информации, чтобы дать какие-либо однозначные ответы, но оптимизатор времени выполнения jvm чрезвычайно мощен и выполняет всевозможные встраивания, анализ данных во время выполнения и анализ escape, а также всевозможные приемы кеширования.* Конечный результат состоит в том, чтобы сделать такие микропроцессоры, которые вы пытаетесь выполнить, практически бесполезными на практике;и крайне трудно понять, что правильно, даже если они потенциально полезны.

Определенно прочитайте http://www.ibm.com/developerworks/java/library/j-benchmark1.html для более полного обсуждения проблем, с которыми вы сталкиваетесь.По крайней мере, вам нужно убедиться:

  1. foo вызывается в цикле, который выполняется тысячи раз
  2. foo () возвращает результат, а
  3. , чтоиспользуется результат

Ниже приводится минимальная начальная точка, предполагая, что foo () нетривиальна и, следовательно, вряд ли будет встроенной.Примечание. Вам все еще следует ожидать развертывания цикла и других оптимизаций уровня кэша.Также обратите внимание на точку останова компиляции горячей точки (я полагаю, что это ~ 5000 вызовов на сервере IIRC), которая может полностью заполнить ваши измерения, если вы попытаетесь повторно запустить измерения в той же JVM.

public class FooBar {
    public static void main(String[] args) {
        int sum = 0;
        int ITERATIONS = 10000;
        for (int i = 0; i < ITERATIONS; i++) {
            sum += foo(i);
        }

        System.out.println("%d iterations returned %d sum", ITERATIONS, sum);
    }
}

Серьезно, вам нужно немного почитать, прежде чем вы сможете добиться значительного прогресса в написании тестов для современной JVM.Те же оптимизации, которые позволяют современному Java-коду соответствовать или даже иногда превосходить C ++, затрудняют сравнительный анализ.

0 голосов
/ 10 августа 2011

Java-компилятору не разрешено выполнять такую ​​оптимизацию, потому что вызовы методов очень вероятно вызывают побочные эффекты, например, действия ввода-вывода или изменения во всех полях, которые он может достичь, или вызов других методов, которые делают это.

В функциональных языках, где каждый вызов функции гарантированно возвращает один и тот же результат, если вызывается с одинаковыми аргументами (изменения состояния запрещены), компилятор может действительно оптимизировать несколько вызовов, запоминая результат.

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

...