Санкт-Петербургская группа тестирования JVM


« Используем JDI | Main | Новые оптимизации... »
20060823 среда Август 23, 2006

Новые оптимизации компилятора VM. Часть 2: Escape-analysis

Мы продолжаем рассказ о новых оптимизациях компилятора JIT виртуальной машины Java HotSpot 1.6. Сегодня речь пойдет о так называемом escape-анализе.

Что представляет собой escape-анализ? Для ответа на этот вопрос сначала необходимо сформулировать исходную проблему.

Представиим себе ситуацию, когда JIT-компилятор начал компиляцию или оптимизацию метода. В общем случае мы предполагаем, что методы, в данный момент выполняющиеся в других потоках, могут изменять любой Java-объект. Однако для объектов, созданных внутри метода, это ограничение может быть смягчено, если удастся доказать, что объект не покидает (escapes) область видимости метода. В соответствии с этим критерием будем называть объекты покидающими и непокидающими.

Пример:

class Escape1 {
    Integer val;
    Escape1 next;

    Escape1(Integer val) { this.val = val }

    void example() {
        Integer i1 = new Integer(1);
        Integer i2 = new Integer(2);
        Integer i3 = new Integer(3);

        Escape e1 = new Escape1( i1 );
        Escape e2 = new Escape1( i2 );
        Escape e3 = new Escape1( i3 );

        e1.next = e2;
        next = e2;		// e2 и i2 покидают метод через указатель this
        e2.next = e3;		// e3 покидает метод через цепочку this => e2
    }
}

Объекты i1, e2, e3 являются покидающими, поскольку они достижимы по ссылкам после выполнения метода example(). В противоположность этому, объекты i1 и e1 не являются покидающими.

Формально объект O назыается непокидающим для метода M, если O:

Escape-анализ, таким образом, сводится к идентификации непокидающих объектов для данного метода. Какие оптимизации позволяет сделать escape-анализ? Вот некоторые примеры:

Типичные примеры ситуаций, в которых встречаются непокидающие объекты:

Теперь обратимся к алгоритму escape-анализа. Для идентификации множества объектов, непокидающих данный метод необходимо проведение вспомогательной процедуры—отслеживания ссылок на объекты. Это—так называемый points-to-анализ. Points-to-анализ—это процесс определения множества объектов, на которые может указывать конкретная ссылка.

В Java HotSpot 1.6 применяется следующий алгоритм escape-анализа:

Остановимся более внимательно на последнем пункте. Если метод не встроен в код, то необходимо отследить, являются ли его аргументы покидающими данный метод, т. к. в противном случае пришлось бы делать пессимистическое предположение о том, что все аргументы покидают метод. Это перечеркнуло бы эффект оптимизации за счет escape-анализа. Кроме того, нельзя целиком полагаться на статический компилятор, т.к. заранее неизвестно, будет ли JIT-компилятор встраивать данный метод или нет. Тем не менее, в JVM имеется оценочный escape-анализатор, работающий на уровне байткода. Данный анализатор сканирует байткод метода и определяет, какие из аргуметов являются покидающими для метода и является ли покидающим возвращаемое значение. Полученная информация сохраняется для дальнейшего использования динамическим компилятором (JIT).

Теперь рассмотрим пример оптимизации совершаемой с помощью escape-анализа:

class Escape2 {
    int fld1, fld2;
    Escape2(int v1, int v2) { fld1 = v1; fld2 = v2; }

    static void bigMethod() {
        // Слишком большой метод, чтобы его встраивать...
    }

    static void example(int v1, int v2) {
        Escape2 e1 = new Escape2(v1, 10);
        Escape2 e2 = new Escape2(v2, 5 - v1);
        bigMethod();
        return e1.fld1 + e2.fld2;
    }
}

Без escape-анализа мы должны предполагать, что bigMethod() может изменить поля объектов e1 и e2. Поэтому после его вызова необходимо заново загрузить значения e1.fld1 и e2.fld2. С другой стороны, escape-анализатор скажет нам, что bigMethod() не мог совершить таких изменений, поэтому возвращаемой значение функции example() будет равно v1 + (5 – v1) = 5.

Вообще говоря, можно пойти далее в области escape-анализа и пытаться вычислять множество объектов, не покидающих какой-либо области внутри метода. Это называется потокозависимым анализом. Потокозависимый анализ имеет большую емкостную сложность (т.е. требует больше памяти для выполнения) и может взаимодействовать с другими оптимизациями компилятора. В серверном компиляторе HotSpot реализован потоконезависимый анализ. А кроме того, имеется прототип потокозависимой версии анализатора. В настоящее время исследуется вопрос о том, можно ли за счет большей сложности потокозависимого алгоритма генерировать лучший код.

На данный момент escape-анализ является прерогативой только серверного компилятора Java SE 6. Escape-анализ отключен по умолчанию, но включить его можно с помощью опции командной строки -XX:+DoEscapeAnalysis.

Игорь Привалов

опубликовал vmrobot ( авг 23 2006, 07:04:07 PM MSD ) Permalink Комментарии [3]

Trackback URL: http://blogs.sun.com/vmrobot/entry/%D0%BD%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%82%D0%BE%D1%80%D0%B0_vm_%D1%87%D0%B0%D1%81%D1%82%D1%8C1
Комментарии:

"с помощью опции командной строки -XX:+UseEscapeAnalysis....." или все такие -XX:+DoEscapeAnalysis?

опубликовал denis_ka Сентябрь 05, 2006 at 11:31 AM MSD #

Наконец-то его сделали! Я уж думал не дожиму :)

опубликовал Александр Октябрь 27, 2007 at 04:46 PM MSD #

/* Объекты i1, e1, e2 являются покидающими, поскольку они достижимы по ссылкам после выполнения метода example(). В противоположность этому, объекты i1 и e1 не являются покидающими. */

вероятно, объекты e2 и e3 являются покидающими, а не e1 и e2 ?

опубликовал 83.242.250.114 Май 30, 2008 at 09:38 AM MSD #

Опубликовать комментарий:

Имя
E-Mail:
URL:

Ваш комментарий:

HTML Syntax: Отключен

Хиты страниц за сегодня: 157