Выполнение метода профилирования - PullRequest
2 голосов
/ 26 апреля 2011

Я пытаюсь профилировать некоторый код, но я сталкиваюсь с некоторыми проблемами из-за того, что я думаю, что компилятор 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

Теперь у меня вопрос, является ли это приемлемым способом профильных методов?Я все еще хотел бы, чтобы в моих методах, которые я профилировал, происходили оптимизации, но не в тестовой установке (по крайней мере, не из-за оптимизаций, которые привели бы к тому, что метод вызывался бы меньше, чем предписанное количество раз, или кешировали результаты между запусками).

Ответы [ 3 ]

4 голосов
/ 26 апреля 2011

Вы должны быть , используя профилировщик , как YourKit или аналогичный для вашего приложения в целом. Сосредоточьтесь на проблемных областях, а не на генераторе случайных чисел, который вряд ли является узким местом любого рода. У вас действительно есть сценарий использования, который потребляет более 80 миллионов в секунду? Почти все остальное займет больше времени, чем эти методы. Вы почти наверняка беспокоитесь о том, что не подходит для большой картины.

Если вы действительно хотите или у вас есть веская причина для продолжения этого подхода, по крайней мере, сначала прочтите это: Как мне написать корректный микростандарт в Java? Существуют всевозможные факторы, которые влияют на микро-тестирование и перевод их в реальный мир редко имеют значение или работают. Профилировщик скажет вам, что вам действительно нужно знать, а на остальное не стоит тратить много времени.

2 голосов
/ 26 апреля 2011

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

0 голосов
/ 26 апреля 2011

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

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

Если вы используете volatile, это может быть дороже, чем то, что вы тестируете, что может быть одной из причин результатовпочти одинаковы при использовании voltile.;)

Простой способ избежать оптимизации цикла JVM до нуля - добавить результаты и распечатать итоги (которые можно игнорировать)

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