Компиляторная оптимизация Java для повторных вызовов метода?

Компилятор 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 ошибка в 43 671 строке).

7
задан Rafe Kettler 2 August 2010 в 03:13
поделиться

3 ответа

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

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

6
ответ дан 6 December 2019 в 19:31
поделиться

Нет; это вызовет большую проблему, если 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);
    }
}
4
ответ дан 6 December 2019 в 19:31
поделиться

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

Конечный результат - сделать микротесты, которые вы пытаетесь выполнить, практически бесполезными; и их чрезвычайно сложно сделать правильно, даже если они потенциально полезны.

Обязательно прочтите 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 ++, действительно затрудняют тестирование.

3
ответ дан 6 December 2019 в 19:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: