Я пытаюсь снизить затраты на производительность/сборку мусора при регистрации операторов. Я хочу иметь множество операторов ведения журнала, которые я мог бы включить для отладки, но также иметь возможность отключить их для быстрой работы.
Я провел тест на вызов следующих методов:
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. Я перепробовал множество настроек компилятора, но, может быть, я что-то упускаю? Как сделать так, чтобы код не генерировал столько мусора, ничего не делая?