Стратегия встраивания HotSpot JIT: сверху вниз или снизу вверх

Предположим, у нас есть 3 метода: метод 2 вызывается из метода 1, метод 3 вызывается из метода 2. Методы 2 и 3 имеют размер 30 байт-кода каждый. Кроме того, предположим, что для определенности метод 2 всегда вызывается из метода 1 ровно один раз, а метод 3 всегда вызывается из метода 2 точно один раз.

Если метод 2 вставлен первым, метод 3 будет вызван непосредственно из тела метода 1 и может быть встроен в свою очередь. Если метод 3 сначала встроен в метод 2, размер последнего станет около 60 байт-кодов, и он не может быть встроен, потому что по умолчанию MaxInlineSize порог 35 байткодов.

В каком порядке методы HotSpot JIT встроены: сверху вниз или сверху вниз?

2 ответа

Решение

MaxInlineSize влияет на компиляцию методов, выполняемых хотя бы один раз, но менее чем MinInliningThreshold только раз. Для методов, выполняемых более чем MinInliningThreshold есть разные настройки -XX:FreqInlineSize=… имеющий намного большее (зависящее от платформы) значение по умолчанию. Горячие точки по-прежнему встроены независимо от MaxInlineSize, Вы можете проверить это, запустив приложение с -XX:+UnlockDiagnosticVMOptions-XX:+PrintInlining-XX:MaxInlineSize=0, Он по-прежнему будет сообщать о "горячих точках" (с комментарием "(горячие)"). Только методы, ранее сообщенные как встроенные с комментарием "выполнено FreqInlineSize Вы можете получить комментарии типа "горячий метод слишком большой". Я никогда не видел их с настройками по умолчанию.

Выполнение приведенного ниже кода с параметрами показывает, что оба метода m3 встроены первыми. я использовал следующие параметры для jvm: -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining, По-видимому, метод, который первым счетчиком выполнения достигает порогового значения для вставки, указывается первым. В нашем случае м3. Таким образом, для точки доступа, которую я использовал для тестирования, m3 сначала выполняется и m2 выполнение заканчивается.

Код был запущен с jdk7_u40 с отключенной TieredCompilation, режим сервера на Windows 8. Вывод команды был:

            @ 66   java.lang.String::indexOfSupplementary (71 bytes)   too big
            @ 21   methodTest::m3 (31 bytes)   inline (hot)
            @ 11   methodTest::m2 (35 bytes)   inline (hot)
              @ 21   methodTest::m3 (31 bytes)   inline (hot)
            @ 14   methodTest::m1 (25 bytes)   inline (hot)
              @ 11   methodTest::m2 (35 bytes)   inline (hot)
                @ 21   methodTest::m3 (31 bytes)   inline (hot)

m1 является 25 bytes по размеру, m2 является 35 bytes а также m3 имеет 31 bytes,

public class methodTest {

    public static void main(String[] args) {
        doTest();
    }

    int i = 0;
    int j = 0;
    int k = 0;

    private static void doTest() {
        methodTest m = new methodTest();

        for (int i = 0; i < 1000000000; i++) {
            m.m1();
        }
        System.out.println(m.i);
        System.out.println(m.j);
        System.out.println(m.k);
    }

    private void m1() {
        i++;
        m2();
        j++;
    }

    private void m2() {
        i++;
        i++;
        m3();
        j++;
    }

    private void m3() {
        i++;
        j++;
        k++;
    }
}
Другие вопросы по тегам