Чи оптимізовано якийсь зворотний виклик двигунів 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.