Как именно V8 оптимизирует / встроенный? - PullRequest
19 голосов
/ 06 ноября 2011

Мне интересно, возможно ли получить знания о том, как именно V8 оптимизирует и оптимизирует вещи?

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


1. Используя предварительно вычисленную константу Math.PI / 180, а затем выполните Math.sin(x * constant).

Я использовал этот код:

var test1 = (function() {
  var constant = Math.PI / 180; // only calculate the constant once

  return function(x) {
    return Math.sin(x * constant);
  };
})();

2. Расчет постоянной на лету.

var test2 = (function() {
  var pi = Math.PI; // so that the compiler knows pi cannot change
                    // and it can inline it (Math.PI could change
                    // at any time, but pi cannot)

  return function(x) {
    return Math.sin(x * pi / 180);
  };
})();

3. Использование буквенных чисел и вычисление константы на лету.

var test3 = (function() {
  return function(x) {
    return Math.sin(x * 3.141592653589793 / 180);
  };
})();

Удивительно, но результаты были следующими:

test1 - 25,090,305 ops/sec
test2 - 16,919,787 ops/sec
test3 - 16,919,787 ops/sec

Похоже, что pi было встроено в test2, так как test2 и test3 приводят к точно одинаковому количеству операций в секунду.

С другой стороны, разделение, по-видимому, не оптимизировано (то есть предварительно рассчитано), поскольку test1 значительно быстрее.

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

Ответы [ 2 ]

7 голосов
/ 06 ноября 2011

Образованное предположение на ваш первый вопрос:

Строго говоря, он не может постоянно сгибать часть pi / 180, потому что вы не делаете pi / 180 во второй и третьей функции.Вы просто делите (x * pi) на 180 (умножение имеет приоритет).

Теперь вы можете спросить, почему он не меняет порядок операций, чтобы получить что-то, что можно оптимизировать (этот процесскстати, называется реассоциация) ... в конце концов, результат эквивалентен (a * b / c = (a * b) / c).Математика так говорит, верно?

Ну, математика так говорит, но математика не использует числа с плавающей запятой.С поплавками все сложнее.x * pi может быть округлено, и тогда изменение порядка приведет к другому результату.Ошибки, вероятно, будут крошечными, но, тем не менее, главное правило оптимизации компилятора таково: вы не должны изменять результат программы.Лучше выполнять неоптимальные результаты в нескольких математических тестах, написанных неудачным образом, чем на пикселе (да, это может быть заметно) в некоторых графических кодах.

3 голосов
/ 28 мая 2016

Чтобы ответить на ваш второй вопрос, вы можете увидеть байт-код, который V8 оптимизировал ваш JS для использования этого инструмента: http://mrale.ph/irhydra/2/.Это фантастика для низкоуровневой настройки кода в Chrome.

...