Branch prediction
Суббота, 13 октября 2012

Есть такая вещь в современных и не очень процессорах, называется предсказатель переходов (branch predictor). Он позволяет значительно увеличить скорость работы процессора. Недавно мне Антон прислал ссылку на обсуждение предсказателя переходов на Stack Overflow. И там есть очень хорошее объяснение, обязательно посмотрите.

Так вот, я решил проверить, насколько всё это применимо к JavaScript. Ведь, хотя это и интерпретируемый язык, во все последние браузеры встроен JIT-компилятор. И логично предположить, что производительность будет страдать от плохо предсказываемых переходов. Как оказалось, идея такого исследования не мне первому пришла в голову и на jsPerf нашелся соответствующий тест. Я добавил еще несколько интересных вариантов и готов поделиться результатами.

Сначала о самом тесте. У нас есть 2 одинаковых случайных массива с числами от 0 до 255. Потом один из них мы сортируем. Ну и смотрим, с какой скоростью посчитается сумма всех элементов массива больших или равных 128.

Есть 2 основных способа это сделать: с помощью if и с помощью тернарного оператора.

var sum = 0;
for (var j = 0; j < arraySize; ++j) {
  if (unsorted[j] > 128) {
    sum += unsorted[j];
  }
}
var sum = 0;
for (var j = 0; j < arraySize; ++j) {
  sum += unsorted[j] >=128 ? unsorted[j] : 0;
}

Ну и третий способ — небольшая оптимизация второго:

var sum = 0, item;
for (var j = 0; j < arraySize; ++j) {
  item = unsorted[j];
  sum += item >=128 ? item : 0;
}

Результаты

Что хочется отметить. У Google Chrome действительно хороший JIT-компилятор, и разница в скорости выполнения хорошо заметна. В случае Firefox не всё так гладко. В оригинальном варианте с if разница в скорости в 2 раза, как и в случае Chrome. А вот тернарный оператор почему-то работает значительно медленнее, и разница между отсортированным и неотсортированным массивом не так заметна. Opera вообще всё равно, хотя проход по отсортированному массиву все-таки немного быстрее. И еще для Opera имеет значение, что мы сделали 1 обращение к элементу массива вместо двух. Подозреваю, что такая оптимизация в ее компиляторе не предусмотрена.

Про Internet Explorer ничего не скажу, у меня его нет. Если не трудно, перейдите по ссылке в IE и нажмите Run Tests.

← Наследование в JavaScript: скандалы, интриги, расследованияСкоро! →