Я довольно новичок в 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 встроить этот метод интерфейса?