Простое присутствие установщиков / получателей ES6 приводит к снижению производительности в несвязанной функции (V8) - PullRequest
2 голосов
/ 18 апреля 2020

1) Создайте объект и дайте ему простой метод, например,

let R = {
  f: (x) => Math.sqrt(x)
}

2) Оцените его производительность, например, вызовите f (x) несколько миллионов раз 3) Теперь добавьте геттер, например,

let R = {
  f: (x) => Math.sqrt(x),
  get h() {return 0}
}

4) Снова отметьте f (x). Производительность в chrome / node (двигатель V8) значительно падает.

Есть какие-нибудь объяснения этой странности?

Вот фрагмент кода для этого: https://codepen.io/iiroullin/pen/XWbwoVQ

Обходной путь:

Кажется, что определение метода получения / установки старого (ES5) способа не нарушает оптимизацию V8. Таким образом, пока они сглаживают все перегибы в ES6, вместо (3) можно использовать это:

Object.defineProperty(R, 'h', {get: () => 0})

и тому подобное для всех получателей / установщиков.

Другое исправление :

Используйте классы, см. Ответ ниже

1 Ответ

2 голосов
/ 18 апреля 2020

Я подал ошибку для этого: crbug.com / v8 / 10429

Можете ли вы описать, в каком сценарии (кроме микробенчмарков) это происходит, в частности по сравнению с определение геттеров на занятиях? Следующее, кажется, быстрое:

class C {
  f(x) { return Math.sqrt(x); }
  get h() { return 0; }
}
let R = new C();

for (...) {
  R.f(...);
}

Полагаю, использование классов для определения нетривиальных объектов в настоящее время считается "наилучшей практикой"; если есть случаи, когда классы не соответствуют требованиям, это было бы полезно знать, чтобы двигатели могли оптимизировать для таких шаблонов.


Примечание: @JaredSmith: термин «deopt» относится конкретно к Ситуация с необходимостью выбросить оптимизированный код, когда предположение, сделанное во время его компиляции, не выполняется. Это не то, что здесь происходит.

...