встраивание метода Java-интерфейса - PullRequest
0 голосов
/ 05 сентября 2018

Я довольно новичок в Java из мира C ++. Я запускаю некоторый серверный код, который запускает метод, метод foo (), который вызывается несколько миллионов раз в секунду. Это код, чувствительный к задержкам, и этот метод также отображается в профилировщике как потребляющий 20% общего использования ЦП процессами.

int foo_old() {
     if (Float.isNan(this.x)) { // shows up in profiling
        res = do some computation; // some floating point comparison, doesn't show up in profiling;
        return res;
     } else {
        // Happens 99% of the time;
        res = do something else; // some floating point comparison, doesn't show up in profiling;
        return res;
     }
}

Есть ли простой способ проверить, будет ли мой метод foo встроен или нет? могу ли я узнать это из информации трассировки стека профилировщика на работающем сервере?

Я попробовал некоторую оптимизацию, пытаясь упростить метод foo (). По сути, в foo есть проверка float.isNan, которая также отображается на профилировщике, удивленная тем, что проверки nan выполняются медленнее. по сравнению с некоторыми другими логическими операциями (меньше, больше, чем сравнение с плавающей запятой) быстрее.

Один из методов, который я попытался, был удалить проверку Nan, т. Е. Потому что я знаю во время компиляции, нужна ли проверке объекта Nan или нет, я попытался сохранить функциональный интерфейс (переменную-член) и назначить этот функциональный интерфейс foo_old (который имеет проверку Nan ) ИЛИ foo_optimized (который не выполняет проверку нанов) на основе свойства объекта, известного на момент создания объекта (в конструкторе объекта я назначаю этому интерфейсу правильную ссылку на метод.

class A {
  final FuncIf test; // Functional interface with same signature as foo_old, foo_new

  public A(bool optimize) {
      test = optimize ? this::foo_optimized : this::foo_old;
  }

  // same as the original foo mentioned above
  int foo_old() {
    ...
   }

  // No nan check
  int foo_optimized() {
        res = do some computation; 
        return res;
  }
}

Теперь, когда я создаю объекты, я знаю во время компиляции / времени создания объекта, какую версию foo использовать. поэтому я назначаю переменную интерфейса для правильной версии foo. После развертывания наблюдается увеличение задержки до <10%. Хотя многие объекты теперь будут использовать оптимизированную версию foo. </p>

Это потому, что foo before был прямым вызовом метода, и как только я использую ссылку на интерфейс, дополнительная косвенная передача виртуального foo - это издержки, которые я вижу в задержке (накладные расходы на вызов метода интерфейса намного больше, чем проверка Nan) сам ?? ) ? Не может ли компилятор jvm встроить этот метод интерфейса?

1 Ответ

0 голосов
/ 05 сентября 2018

Единственное образованное предположение состоит в том, чтобы измерить его bytecode. Для этого используйте javap. В основном JVM имеет два компилятора C1 и C2; оба могут встроить этот метод.

Есть три параметра, о которых JVM заботится при встраивании (ну, это те, о которых я знаю, я также знаю, что есть много больше):

-XX:MaxInlineSize (35 by default)
-XX:FreqInlineSize (325 by default)
-XX:MinInliningThreshold (250 by default)

Если ваш метод вызывается менее чем MinInliningThreshold (250), он подчиняется правилу MaxInlineSize, что означает, что если он меньше 35 байтов, он будет встроенным. Если он называется более чем то, чем он подчиняется FreqInlineSize, что составляет 325 байт (намного больше).

Что вы также можете сделать, это напечатать то, что встраивается или нет, через некоторые параметры:

-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining

В результате запуска таких сообщений вы можете увидеть такие сообщения:

  callee is too large

это печатается C1 и говорит вам, что MaxInlineSize превышено для этого скомпилированного метода. Или:

  too big

печатается компилятором C2 при превышении MaxInlineSize. Или:

  hot method too big

напечатано C2 при превышении FreqInlineSize.

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