2016-03-22 1 views
2

У меня есть jsperf test case, и результат довольно запутанный. У меня есть три «фрагменты»:Как я могу избежать «оптимизации» моих тестовых примеров javascript?

  • умножения
  • деление
  • управления (ни операция выполняется)

и большую часть времени, все они выходят примерно с той же скоростью .. даже контроль! Я догадался, что JS JIT-компилятор был removing my "unnecessary" instructions, когда они, похоже, не имели никакого эффекта; поэтому я начал accumulating the results, and logging them to the console, когда тестовый цикл был выполнен, например.

for (var i = 0; i < nNumbers; i++) { 
    result += a[i]/b[i]; 
} 
console.log(result); 

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

Итак, я попытался прокрутить число итераций внутри каждого «фрагмента», чтобы свести к минимуму количество записей в журнале относительно операций, которые я пытаюсь проверить. Но у меня все еще нет существенной разницы в скорости между тремя фрагментами. Действительно, деление и умножение имеют одинаковую скорость, как оценка константы ?? Я должен делать что-то неправильно. Или jsperf сломан.

Уже есть ответы на связанные вопросы, но ни один из них, который я нашел для теста Javascript.

+0

Я получил, ops сек: mult: 126k, div: 33k, control: 282k, как и ожидалось, так как разделение медленное для компьютеров. http://jsperf.com/multiplication-vs-division-lars/2 – dandavis

+0

@dandavis Я получаю аналогичные результаты – BeyelerStudios

+1

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

ответ

1

Не помещайте console.log в твоих синхронизированных разделах. Это ужасно медленно в сравнении с операциями, которые вы на самом деле хотите измерить, поэтому он искажает ваши результаты. Кроме того, как вы заметили, это зависит от времени, когда консоль открыта или нет.

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

Конечно, это не обязательно предотвращает loop-invariant code motion, поэтому вам также необходимо убедиться, что ваш синхронизированный код всегда работает с разными данными.

+0

Можете ли вы привести пример размещения результатов в глобальном массиве? Если я объявляю «var results» в коде 'setup', это глобальная переменная или мне нужно поместить ее в код подготовки? Должен ли он быть массивом, а не одной (скалярной) переменной? (Что касается цикла-инвариантного кода, я считаю, что мои тестовые фрагменты уже невосприимчивы к этому, поскольку каждая итерация через цикл работает на 'a [i]' и 'b [i]', где 'i' является переменная цикла.) – LarsH

+0

Включение объявления в установочный код может быть достаточно, но не является действительно глобальным - зависит от того, насколько продвинутый оптимизатор. Скаляр, который вы добавите, должен работать, но скаляр, который вы только перезаписываете, вероятно, не будет. – Bergi

+0

Я не вижу способа поставить результаты в глобальную переменную. Я попытался переместить объявление «результата» (исключительно на самом деле) в код подготовки (см. Http: // jsperf.com/multiplication-vs-division-global-results), но теперь я получаю «ReferenceError: result not defined» в каждом фрагменте. – LarsH