Оптимизирует ли JVM псевдонимы переменных? - PullRequest
2 голосов
/ 09 марта 2012

Мне любопытно.Если я создаю несколько локальных переменных, которые используются просто как псевдонимы для других переменных (то есть новой переменной «псевдоним» просто присваивается значение какой-либо другой переменной, и назначение псевдонима никогда не меняется), оптимизирует ли JVM это с помощьюнапрямую использовать исходные переменные?

Скажем, например, что я пишу (неизменяемый) класс кватернионов ( кватернион - это вектор с четырьмя значениями).Я пишу multiply() метод, который принимает другой Quaternion, умножает два и возвращает полученный Quaternion.Чтобы сэкономить на наборе текста и повысить удобочитаемость, я делаю несколько псевдонимов перед выполнением фактических вычислений:

public class Quaternion {

    private double[] qValues;

    public Quaternion(double q0, double q1, double q2, double q3) {
        qValues = new double[] {q0, q1, q2, q3};
    }

    // ...snip...

    public Quaternion multiply(Quaternion other) {
        double a1 = qValues[0],
                 b1 = qValues[1],
                 c1 = qValues[2],
                 d1 = qValues[3],

                 a2 = other.qValues[0],
                 b2 = other.qValues[1],
                 c2 = other.qValues[2],
                 d2 = other.qValues[3];

        return new Quaternion(
                    a1*a2 - b1*b2 - c1*c2 - d1*d2,
                    a1*b2 + b1*a2 + c1*d2 - d1*c2,
                    a1*c2 - b1*d2 + c1*a2 + d1*b2,
                    a1*d2 + b1*c2 - c1*b2 + d1*a2
                );
    }

}

Так что в этом случае JVM обойдется без a1, b1 и т. Д.просто используйте qValues[n] и other.qValues[n] напрямую?

Ответы [ 4 ]

2 голосов
/ 09 марта 2012

Псевдонима не существует, как вы описали его в Java. Когда вы присваиваете значение из одной ячейки памяти новой переменной, JVM создает копию этого значения. Если бы это создало псевдоним, изменение базовых массивов во время вычисления из другого потока изменило бы результат. В вашем примере этого не происходит, потому что вы специально указали JVM сначала сделать копии значений.

Если вы беспокоитесь о производительности, не беспокойтесь. Корректность программы превосходит все проблемы производительности. Любая программа, которая дает неверные результаты быстрее, бесполезна. Я не говорю, что доступ к массивам непосредственно внутри вычислений обязательно приведет к неверным результатам, поскольку я не видел остальную часть кода, но я говорю, что этот тип микрооптимизации не стоит ваших усилий без предварительного нахождения проблема с производительностью и последующие временные тесты, чтобы проверить, где находится эта проблема.

1 голос
/ 09 марта 2012

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

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

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

1 голос
/ 09 марта 2012

Компилятор javac этого не сделает.Разборка простого фрагмента кода, подобного следующему:

    int a = 1;
    int b = a;
    System.out.println("" + (a - b));

Показывает:

   0: iconst_1      
   1: istore_1      
   2: iload_1       
   3: istore_2
   ...

Но это то, что будет выполнять интерпретатор (и даже интерпретатор иногда может выполнить некоторую базовую оптимизацию),JIT-компилятор будет обрабатывать такие виды оптимизации и многие другие;в случае с вашим методом он даже достаточно мал, чтобы его можно было встроить, так что вы даже не получите накладных расходов на вызов метода после того, как JIT включится.

(например, в моем примере JIT может очень легкоделать постоянное распространение и просто покончить с переменными и вычислениями, просто вызывая с помощью "" + 0 в качестве аргумента метода println ().)

Но, в конце, просто следуйте тому, что всегда говорят JIT-хакеры: напишите свой код, чтобы его можно было поддерживать.Не беспокойтесь о том, что JIT будет или не будет делать.

(Примечание: Дэвид прав в том, что переменные - это не псевдонимы, а копии оригинальных значений.)

0 голосов
/ 09 марта 2012

Ваша программа должна работать, но ответ на ваши вопросы - нет.JVM не будет обрабатывать a1 как псевдоним qValues[0], вместо этого он копирует значение последнего в первое.

Проверьте этот хороший референс: http://www.yoda.arachsys.com/java/passing.html

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