Интерпретация тестов производительности для ненулевой проверки

#javascript

#javascript

Вопрос:

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

Мой самый простой тест производительности дал аналогичные результаты в Chrome (все переменные просто объявляются глобально, первая занимает ~ 9 мс, вторая ~ 7,5 мс):

 input = Array.from({ length: 1000000 }, () => Math.random() > 0.8 ? 0 : Math.random() * 1000000000 );
start = performance.now();
for (let i = 0; i < 1000000; i  ) {
  input[i] = input[i] === 0 ? 0 : 1;
}
console.log(performance.now() - start);
 

и

 input = Array.from({ length: 1000000 }, () => Math.random() > 0.8 ? 0 : Math.random() * 1000000000 );
start = performance.now();
for (let i = 0; i < 1000000; i  ) {
  input[i] = ((input[i] | (~input[i]   1)) >>> 31) amp; 1;
}
console.log(performance.now() - start);
 

Принимая во внимание, что сам цикл и назначение уже занимают много времени (~ 4,5 мс), второй потенциально занимает на ~ 33% меньше времени, что, однако, намного меньше, чем я ожидал (и в пределах погрешности измерения, например, в FireFox, оба занимают намного больше времени,и второй на ~ 33% хуже).

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

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

Ответ №1:

Да, скорее всего, это результат сочетания эффектов измерения и JIT-компилятора.

Особенно хорошо, что JIT-компилятор, основанный на эвристике, в современных браузерах JS настолько хорош, что у вас не будет никаких шансов визуализировать «реальное» преимущество в производительности интуитивно более быстрого оператора.

Разница в моем браузере настолько велика, что обоим кодам требуется примерно одинаковое время (для запуска в Opera), что подчеркивает ваш эффект в FF.

Радуйтесь, что вы обнаружили это преимущество в 1,5 мс, большего вы не увидите.

Комментарии:

1. Я, вероятно, не буду использовать «оптимизацию», потому что она гораздо менее читабельна и не влияет на скорость, поэтому в пределах точности измерения (не могу определить, что быстрее). PS: читая связанную статью, я увидел node --trace-opt --tracedeopt и быстро заметил, что перенос цикла for в IIFE также ускоряет процесс, потому что из-за console.log for me произошел шаг деоптимизации. Я еще больше убедился, что все это снова мираж, и на самом деле измерение того, что быстрее в реальном приложении, невозможно сделать с помощью того, что я сделал.