Почему этот код JavaScript работает медленнее после оптимизации Node.js - PullRequest
0 голосов
/ 27 февраля 2019

Я создавал решение проблемы ICPC , используя JavaScript и Node.js , когда столкнулся с интересной проблемой: при определенных обстоятельствах моя программа работала в два раза медленнеетот же набор данных.

Я сократил его, пока не добрался до этого минимального примера, демонстрирующего поведение:

function solve(arr) {
  const total = arr.reduce((a, c) => a + c, 0);
  const count = arr.length;
  for (let i = 0; i < total; i++) {
    for (let j = 0; j < count; j++) {
      // calculate some stuff
    }
  }
}

for (let i = 0; i < 10; i++) {
  // generate some sample data (array of 5000 random numbers 1-10)
  const data = [];
  for (let i = 0; i < 5000; i++) {
    data.push(Math.floor(Math.random() * 10) + 1);
  }

  const start = new Date();
  solve(data);  // run solve on the data
  console.log(`${i + 1}: ${new Date() - start}ms`);
}

Это результат работы node --trace-opt code.js с использованием Node v10.15.1:

[marking 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> for optimized recompilation, reason: small function, ICs with typeinfo: 5/7 (71%), generic ICs: 0/7 (0%)]
[compiling method 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> using TurboFan OSR]
[optimizing 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> - took 1.453, 0.702, 0.082 ms]
1: 86ms
[marking 0x005062b82581 <JSFunction (sfi = 000001DA56AD8BD9)> for optimized recompilation, reason: hot and stable, ICs with typeinfo: 22/23 (95%), generic ICs: 1/23 (4%)]
[compiling method 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> using TurboFan]
[optimizing 0x005062b82521 <JSFunction solve (sfi = 000001DA56AD8CD9)> - took 0.159, 0.632, 0.096 ms]
2: 82ms
3: 80ms
[compiling method 0x005062b82581 <JSFunction (sfi = 000001DA56AD8BD9)> using TurboFan OSR]
[optimizing 0x005062b82581 <JSFunction (sfi = 000001DA56AD8BD9)> - took 0.592, 2.312, 0.154 ms]
4: 245ms
5: 243ms
6: 236ms
7: 237ms
8: 240ms
9: 246ms
10: 239ms

Во время первых трех итераций время выполнения составляет около 80 мс, но перед четвертой итерацией Node перекомпилирует и оптимизирует метод, и с этого момента код выполняется около 3в разы медленнее .

Обычно, когда Node выполняет анализ, перекомпиляцию и оптимизацию во время выполнения, все работает быстрее.

Может кто-нибудь объяснить, почему оптимизация Node делает вещи намного хуже в этомcase?


Обратите внимание, что если код примера изменяется для вычисления total путем итерации вместо использования reduce, оптимизация повышает производительностькак и ожидалось (время выполнения падает до 60 мс):

let total = 0;
for (let v of arr) total += v;

1 Ответ

0 голосов
/ 04 марта 2019

Я отправил отчет об ошибке и получил следующий ответ от Chromium dev:

Некоторые встроенные массивы использовали подсказки веток для проверки границ цикла,в результате чего весь код после встроенного встроенного кода становится отложенным кодом.Это отрицательно сказывается на производительности.

Получается, что это известная проблема с компилятором TurboFan и , исправление было создано и в настоящее время тестируется:

Этот CL удаляет подсказки, которые значительно улучшают планирование кода, на микропроцессоре из связанной ошибки в 3 раза.

...