Чи оптимізовано якийсь зворотний виклик двигунів JavaScript (TCO)?


91

У мене є хвіст-рекурсивний алгоритм пошуку шляхів, який я реалізував у JavaScript, і я хотів би знати, чи може якийсь (усі?) Браузер отримувати винятки із переповнення стека.


2
Це насправді рекурсивний алгоритм, або ітераційний алгоритм, реалізований з рекурсією? Я розумію, що TCO може допомогти лише з останніми.
— nmichaels

1
Я просто хочу додати, що TCO - це не onlyоптимізація. Підтримка його повинна бути частиною специфікації мови, а не компілятора / інтерпретатора, оскільки код, написаний проти одного інтерпретатора / компілятора з TCO, ймовірно, не буде працювати на інтерпретаторі / компіляторі без TCO.
— Гофман

1
Ви можете побачити поточну підтримку та спостерігати за її розвитком у двигунах у таблиці сумісності ES6 Kangax тут: kangax.github.io/compat-table/es6/…
— Рой Тінкер,

Відповіді:


47

Специфікація ECMAScript 4 спочатку збиралася додати підтримку TCO, але її було скасовано:

Немає більше викликів у хвості в JavaScript?

Наскільки мені відомо, в даний час жодна широкодоступна реалізація JavaScript не робить автоматичних TCO. Це може бути вам корисно, хоча:

Оптимізація хвоста

По суті, за допомогою шаблону акумулятора досягається той самий ефект.


1
Просто носій інформації, Rhino має автоматичну TCO разом із Продовженнями в режимі "інтерпретації" (opt = -1) wiki.apache.org/cocoon/RhinoWithContinuations
— Марк Портер,

5
(вибачте за тролінг) ECMAScript 6 включив у специфікацію TCO, який називають належними викликами.
— морозний

@sclv: Яке посилання на батут?
— bukzor

39
Структура акумулятора не дає такого самого ефекту, як TCO. Він просто перетворює рекурсивні алгоритми в хвостово-рекурсивну форму. Це є необхідною умовою для того, щоб TCO був можливим, але він не може замінити його. Ви все одно будете дути стек мовою, яка не оптимізує зворотні дзвінки.
— Марсело Кантос,

"в даний час жодна широко доступна реалізація JS не виконує автоматичну TCO", це неправильно станом на Node 6.2.0, якщо ви передаєте правильний прапор
— Janus Troelsen,

26

Наразі немає радості, але, на щастя, для Harmony заплановані правильні виклики хвоста (версія ECMAScript 6) http://wiki.ecmascript.org/doku.php?id=harmony:proper_tail_calls


1
@MarkWilbur Питання стосувалося саме браузерів , а не всіх існуючих реалізацій ECMAScript.
— марний код

1
@UselessCode Ні, це питання стосується "двигунів Javascript", тож ... не лише браузерів
— BT

1
@BT Насправді існує багато не браузерних середовищ JS, і в заголовку використовуються більш загальні "двигуни Javascript", але в тілі питання вказується "... хотілося б знати, чи може якийсь (усі?) Браузер отримати стек" винятків із переповнення ".
— марний код

Я маю протиставити "але в назві сказано ...". Думаю, оскільки він згадує і те, і інше, питання стосується обох. Але ти маєш рацію, якщо кажеш, що це не робить відповідь застарілою.
— BT

4
@MarkWilbur Наскільки мені відомо, вузол використовує ту саму версію v8, що і chrome - яка на даний момент не підтримує TCO, я мав суть з JS та оптимізований асемблер, який виробляє поточний V8 - gist.github.com/mcfedr / 832e3553964a014621d5
— mcfedr

12

Практично кожен браузер, з яким ви стикаєтесь, спричинить "занадто велику рекурсію". Ось запис у відстежувачі помилок V8, який, мабуть, буде цікавим для читання.

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


Нарешті помилка була прийнята. Це під епосом: "Feature Request Harmony". Сподіваємось, це означає, що вони планують додати його до підтримки ES6 у V8.
— Txangel

Ви можете проголосувати за підтримку TCO в Internet Explorer тут: wpdev.uservoice.com/forums/257854-internet-explorer-platform/…
— Рой Тінкер,

12

В майбутньому в суворому режимі ECMAScript 6 буде підтримуватися оптимізація хвостових викликів. Перевірте http://www.2ality.com/2015/06/tail-call-optimization.html для деталей.

Перевірте http://kangax.github.io/compat-table/es6/ для поточної підтримки двигуна.

На даний момент (18-07-2019) такі двигуни підтримують оптимізацію хвостового виклику:

  • Сафарі> = 10
  • iOS> = 10
  • Kinoma XS6
  • Дуктапе 2.3

підтримка, якщо прапорець "експериментальні функції JavaScript" увімкнено:

  • Вузол 6.5
  • Chrome 54 / Opera 41 Поточна версія таблиці compat її більше не містить

3

Оптимізація хвостових викликів тепер доступна в LispyScript, який компілюється в JavaScript. Детальніше про це ви можете прочитати тут .


А як щодо взаємної рекурсії?
— кішка

2

На даний момент жодна реалізація JavaScript не розпізнає рекурсію хвоста. Зміни вносяться до ECMAScript 6 , і, як казали інші, на V8 є відкритий квиток .

Тут ви можете побачити згенерований V8 асемблер для функції рекурсії хвоста:

Приклад того, як V8 компілює рекурсію

Порівняйте це з тим, як Clang скомпілював ту саму функцію в C

Приклад рекурсії хвоста компілятора C.

V8 зберігає рекурсивний виклик, тоді як компілятор C розпізнав хвостову рекурсію і змінив її на цикл.


"На даний момент жодна реалізація JS не розпізнає рекурсію хвоста." це неправильно станом на вузол 6.2.0, але вам потрібно пройти прапор
— Янус Трольсен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.