Я пытаюсь профилировать некоторый код, но я сталкиваюсь с некоторыми проблемами из-за того, что я думаю, что компилятор Java является умным и изменяет способ работы кода.
примеры методов:
public int method1(int bits)
{
// seed is a long object field
seed = seed * 0x5DEECE66DL + 0xBL & (1L << 48) - 1;
return (int) (seed >>> 48 - bits);
}
public int method2(int bits)
{
// seed is a long object field
seed *= 0x5DEECE66DL;
seed += 0xBL & (1L << 48) - 1;
return (int) (seed >>> 48 - bits);
}
public int method3(int bits)
{
// multiplier, seeds, n, and carry are long/long array object fields
final long t = multiplier * seeds[n] + carry;
// carry = t / b (done in an unsigned way)
final long div32 = t >>> 32; // div32 = t / (b+1)
carry = div32 + ((t & 0xFFFFFFFFL) >= 0xFFFFFFFFL - div32 ? 1L : 0L);
// seeds[n] = (b-1)-t%b (done in an unsigned way)
seeds[n] = 0xFFFFFFFEL - (t & 0xFFFFFFFFL) - (carry - div32 << 32) - carry & 0xFFFFFFFFL;
final long result = seeds[n];
n = n + 1 & r - 1;
return (int) (result >>> 32 - bits);
}
Теперь, чтобы сравнить производительность, я использую этот тестовый стенд:
// gen is the object containing the methods/fields
int result;
long start = System.currentTimeMillis();
for (int i = 0; i < 0x7FFFFFFF; ++i)
{
result = gen.method1(32);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
for (int i = 0; i < 0x7FFFFFFF; ++i)
{
result = gen.method2(32);
}
end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
for (int i = 0; i < 0x7FFFFFFF; ++i)
{
result = gen.method3(32);
}
end = System.currentTimeMillis();
System.out.println(end - start);
Однако результаты, которые я получаю, довольно странные:
7
3109
13402
method1
и method2
должны иметь примерно одинаковое время вычислений, поскольку они вычисляют одну и ту же вещь.method3
Я могу понять, что нужно больше времени, но, глядя на количество вычислений, ни один из трех результатов не кажется мне достаточно длинным.Мне кажется, это указывает на то, что Java каким-то образом оптимизирует мой тестовый стенд и не запускает его все 0x7FFFFFFF
раз.
Чтобы исправить это, я подумал об объявлении result
как поля static volatile
(внеметод испытательного стенда), и это дало правдоподобные результаты:
21814
21468
26962
Теперь у меня вопрос, является ли это приемлемым способом профильных методов?Я все еще хотел бы, чтобы в моих методах, которые я профилировал, происходили оптимизации, но не в тестовой установке (по крайней мере, не из-за оптимизаций, которые привели бы к тому, что метод вызывался бы меньше, чем предписанное количество раз, или кешировали результаты между запусками).