Затраты (скорость и мусор) на вызов функций, которые ничего не делают - PullRequest
4 голосов
/ 22 июня 2010

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

Я выполнил тестирование при вызове следующих методов:

public static final isLogging = false; 

public static logObjs(Object[] params) {
  if(isLogging)
    System.out.println(params[0]);
}

public static log3Obj(Object a, Object b, Object c) {
  if(isLogging)
     System.out.println(a);
}

public static logInts(int a, int b, int c) {
  if(isLogging)
    System.out.println(a);
}

Я сравнил функции с методом драйвера

long sum = 0;
for(int i = 0; i < 100000000; ++i) {
   int a = i; int b = i+1; int c = i+2;
   logFoo(a,b,c);
   sum += a; }

logObjs (i, i + 1, i + 2) занимает около 2 секунд для 1e8 итераций и производит много мусора.Источниками, как я полагаю, являются автобокс целых чисел и создание Object [] для переменной # параметров.

log3Obj производит много (хотя и меньше) мусора и занимает около 1,2 секунды;опять же, я предполагаю, что автобокс все еще происходит.

logInts очень быстр (0,2 с), так же быстро, как цикл без вызова функции.

Итак, проблема в том, что хотя функция детерминистически ничего не делает,Автобокс все еще происходит.В моем коде я бы предпочел, чтобы isLogging не был окончательным, а скорее, чтобы это был параметр времени выполнения, но для этого это более простой случай (когда компилятор может доказать, что функция ничего не делает)должен бежать.Конечно, я могу заменить все свои записи в журнале на

if(isLogging)
   logObjs(a, b, c);

, но это очень не элегантно.Я думал, что это то, что JIT должен заботиться.Я пробовал кучу настроек компилятора, но, может быть, что-то мне не хватает?Как сделать так, чтобы код не генерировал столько мусора, ничего не делая?

Ответы [ 3 ]

4 голосов
/ 22 июня 2010

Вы должны действительно предпочесть существующую структуру ведения журналов, такую ​​как Log4J, а не изобретать велосипед.Эти ребята приложили больше усилий для оптимизации своей системы ведения журналов, чем вы когда-либо реально могли бы иметь.См. Раздел «Производительность» в конце этого Краткого введения в log4j .

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

1 голос
/ 22 июня 2010

Я думаю, что вы должны записывать то, что вам нужно, вместо того, чтобы преобразовывать целые числа в объекты.

Вызов logObjs () или log3Obj () для записи целых чисел - просто пустая трата времени - вы собираетесь создавать временные объекты для упаковки / распаковки, и их нужно будет утилизировать. С этим ничего не поделаешь.

Я подозреваю, что большую часть времени, когда вы будете вызывать logObjs (), вы будете передавать реальные объекты в функцию, и в этом случае стоимость GC будет почти равна нулю, так как вы просто будете передавать ссылки на эти объекты в logObjs () и создание или удаление объекта не требуется.

Напишите несколько функций ведения журнала, которые принимают разные списки аргументов, соответствующие тому, что вы собираетесь записывать в это время. Это то, чем я занимаюсь. Если мне нужно записать строку и 32-битное значение, у меня есть API регистрации с этими параметрами и т. Д. Нет (или немного) ненужного / временного создания объекта.

Если вам нужно зарегистрировать 3 целых числа, напишите API, которое принимает 3 целых числа. Если вам нужно зарегистрировать объект подкабливания, объект колебания и объект без выпадения, напишите API для этого тоже. Минимизируйте эффекты box / unobx / GC, используя соответствующие API для ваших функций ведения журнала.

1 голос
/ 22 июня 2010

Это очень похоже на вопрос: Будет ли оптимизатор Java удалять конструкцию параметров для пустых вызовов методов?

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

Я бы предложил создать несколько методов журнала, общий с некоторыми параметрами vararg и некоторыми перегруженными, в первую очередь принимая целые числа и предотвращая автобокс:

Log(Object... arguments) { /* do logging */ }
Log(Object a, Object b, Object c}  { /* special case for 3 objects */ }
Log(int a, int b, int c}  { /* special case for 3 ints */ }

ОБНОВЛЕНИЕ: еще лучше, см. Петер Тёрёк: «Не изобретай колесо» ответ ...

...