Вбивці оптимізації JS вже не такі страшні

Рік тому я побачила переклад Вбивці оптимізації, і була здивована тим, скільки потрібно тримати в голові, щоб писати оптимізований js код. Практично весь es6 потрапляв під деоптимизацию.


Новий симулятор в v8, званий TurboFan, за останній рік навчився оптимізувати практично весь es5/es6 і навіть try-catch більше не є проблемою.

class TestClass {
megaFunc() {
try {
let sum = 0;
for (let val [1, 2, 3]) {
sum += val;
}
throw new Error(`sync error, sum = ${sum}`);
}
catch(err) {
return err;
}
}
}
let test = new TestClass();
checkOptimizationStatus(test.megaFunc);

Function is optimized by TurboFan

Що залишилося не оптимізованим, а так само як перевірити свою функцію на предмет оптимізації або деоптимизации буквально в 1 дію можна побачити під катом

2. Непідтримуваний синтаксис
На даний момент не оптимізуються:

  • функції-генератори;
  • функції, що містять вираз for-of;

  • функції, що містять вираз try-catch;
  • функції, що містять вираз try-finally;
  • функції, що містять складовою оператор присвоювання let;
  • функції, що містять складовою оператор присвоювання const;
  • функції, що містять об'єктні літерали, які, в свою чергу, містять оголошення __proto__, get або set.
Швидше за все, неоптимизируемы:

  • функції, що містять вираз debugger;
  • функції, викликають eval();
  • функції, що містять вираз with.
Рік тому цей список здавався значним, на даний момент зі списку не оптимізується тільки debugger, генератори і "__proto__, get або set", навіть try-catch більше не вимагає трюку з tryCatch.

3. Використання arguments
Існує чимало способів використовувати arguments так, що оптимізувати функцію буде неможливо. Так що при роботі з arguments слід бути особливо обережними.
...
З arguments все просто, швидше за все їх не будуть оптимізувати, і вже досить легко можна перейти на rest параметри, з якими можна працювати як завгодно.

4. Switch-case
Вираз switch-case на сьогоднішній день може мати до 128 пунктів case, і якщо перевищити це кількість, що містить даний вираз функція не зможе бути оптимізована.
Тепер навіть 500 case не викликають деоптимизацию, 600 теж.

5. For-in
Вираз For-in може декількома способами перешкодити оптимізації функції. 5.1. Ключ не є локальною змінною
5.2. Итерируемый об'єкт не є «простим перечисляемым»
5.2.2. У ланцюжку прототипів об'єкта є поля з перерахованими значеннями
5.2.3. Об'єкт містить перераховуються індекси масиву
Оптимізується все, окрім ситуації коли key для for-in визначено ззовні функції (але так все одно ніхто писати не буде):

var key;
function nonLocalKey2() {
var obj = {}
for(key in obj);
}

6. Нескінченні цикли зі складною логікою умов виходу або з неясними умовами виходу
Не вдалося підібрати такий нескінченний цикл, щоб вийшла деоптимизация.

Як перевірити свої функції на предмет оптимізації самостійно
Зробити це досить просто і для хрому і для ноди. В обох випадках потрібно лише запустити їх з прапором --allow-natives-syntax

Для chrome створюємо ярлик:

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --js-flags="--allow-natives-syntax"

Файли index.html

< script src="index.js"></script>

і index.js

function exampleFunction() {
return 3;
eval(");
}

checkOptimizationStatus(exampleFunction)

function checkOptimizationStatus(exampleFunction) {
exampleFunction();
exampleFunction();
%OptimizeFunctionOnNextCall(exampleFunction);
exampleFunction();

switch (%GetOptimizationStatus(exampleFunction)) {
case 1: console.log("Function is optimized"); break;
case 2: console.log("Function is not optimized"); break;
case 3: console.log("Function is always optimized"); break;
case 4: console.log("Function is never optimized"); break;
case 6: console.log("Function is maybe deoptimized"); break;
case 7: console.log("Function is optimized by TurboFan"); break;
default: console.log("Unknown optimization status"); break;
}
}

І просто відкриваємо index.html у браузері. Потреби в веб-сервері немає, просто звичайна html-сторінка.

Для node ще простіше:

node --allow-natives-syntax index.js

Функція-обгортка checkOptimizationStatus(yourFunction) покаже статус оптимізації, досить викликати її передавши в якості параметра вашу функцію

Підсумок
Нові оптимізація з'являються досить швидко, тому просто викиньте з голови жахливий список убивць оптимізацій і спокійно пишіть на js в звичному стилі

PS: В chrome 55 з'явилася підтримка async-await без прапора, в ноді починаючи з 8 гілки, промис-функції успішно оптимізуються, значить не довго чекати коли і async-await теж будуть оптимізуватися.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.