LINUX.ORG.RU

История изменений

Исправление stevejobs, (текущая версия) :

Ну для начала, я не думаю, что «настоящий JS» вообще можно скомпилировать в натив ;) У тебя будет, скорей всего, какая-то часть интерпретируемая и какая-то компилируемая. Просто по стандарту языка.

Для Java в GraalVM (SVM, Native-Image) просто сказали, что мы не сможем так писать на «настоящей Java», мы будем писать на джава-подобном языке с огромными ограничениями. И это камень преткновения, потому что если ты разрабатываешь на обычной Java и только для прода компилируешь под Native-Image в экзешник, то вступают в силу все эти ограничения, и зачастую людям приходится переписывать свой код, потому что они недостаточно хорошо держали в голове эти ограничения.

Что касается перформанса, то тут трудно сказать. Скорей всего, компилируемая нода будет медленней тупо потому, что ты пишешь ее в 1 рыло, а V8 пишет толпа очень квалифицированных программистов гугла, которые могут чуть ли не на ассемблере вылизывать её для конкретных случаев. Грубо говоря, в GraalVM тоже есть свой интерпретатор JS, и хотя он тоже очень неплох, в некоторых тестах он сливает V8 подчистую, например в тестах на регулярные выражения, там в V8 прямо произведение искусства понаписано.

Если же представить, что допустим вы пишете одинаковыми силами, то тут уже возникают теоретические вопросы, да. Например гляди, в V8 никогда не JIT-компилируются методы, у которых больше 3 параметров в функции, или больше пяти, уже не помню. Если хочешь сделать функцию, которая тормозит на V8 - просто сделай ей побольше параметров, JIT ее не тронет и она будет там как кость в горле. А не трогает он её именно из-за того, что для специализации и частичной компиляции метода под разные параметры нужно потратить слишком много кодкэша. Условно говоря, метод которому на вход постоянно приходят три инта, и метод которому на вход приходит три строки - должны компилироваться радикально разными способами. Теперь представь метод, у которого постоянно меняются типы входных параметров - иногда это инты, а иногда строки, а иногда что-то ещё. Тебе нужно перебрать и скомпилировать все возможные частичные спецализации. Это тупо комбинаторный взрыв, если делать по-простому. (По сложному сделано в фреймворке Truffle из GraalVM, на котором написан Graal.js, он справится и с более чем тремя, но там очень сложный способ, я его не объясню в этом комментарии). Чтобы не иметь с этим дела, чуваки из Гугла просто не компилируют ничего, где много параметров. Для маленького количества параметров они начинают выводить «временные типы» скорей всего, я бы так сделал, но это надо уже копаться в доках на TurboFan/Ignition чтобы понять как по-настоящему. Но вот проблема, методы с большим количеством параметров и методы с переменными типами в JS - это норма, так все делают. И тебе придётся компилировать их по-честному. И либо тебе придётся брать сразу самый обобщённый вариант (и это будет очевидно всегда медленней, чем частичная специализация - два произвольных объекта сильно сложней сложить, чем два инта), либо устраивать комбинаторный взрыв и компилировать вечно. В целом, твой «компилируемый V8» будет на таких методах работать всегда менее удовлетворительно для пользователя, чем JIT по методам с короткой сигнатурой.

Короче, это можно очень долго теоретизировать, попробуй написать что-нибудь сам и посмотреть на результаты, погоняв какие-то синтетические тесты вроде моего [Carbon](https://github.com/graalvm-community/graalvm-carbon) (это гугловый Octane, перепакованный в один файл, чтобы легко запускать на Ноде). Кажется, это хорошая тема для мастерского тезиса или что-то такое, если ты найдёшь какую-то достаточно интересную тему чтобы проверить. Если вдруг будешь такое делать, то очень советую читнуть работы по GraalVM за авторством Вертингера и ко, он начинался точно так же, они делали универсальный фреймворк для интерпретации на примере JS движка.

Олсо, в языке-Java таких проблем нет, т.к. типы настоящие, фиксированные. Более фиксированные типы есть в TypeScript, и у нас на следующей HolyJS [будет докладчик](https://holyjs-moscow.ru/2019/msk/talks/4y3sifyqmh036vhhecbqfr/), который собирается рассказать про компиляцию TS, но у меня есть заранее предположения, что там будет: если TS-компилятор должен обрабатывать вообще весь язык, а не closed world мира TS, то мы приходим к обобщенной программе на JS, для которой AOT-компиляция не имеет смысла.

На самом деле, весь этот вопрос можно решить тем, чтобы компилировать не весь JS целиком, а только какое-то особое подмножество, которое будет стабильно генерить одинаковые временные типы для огарниченного прямо в компиляторе количества параметров (указал больше пяти - это ошибка компиляции). Но это тема для совершенно другого ответа :)

Исходная версия stevejobs, :

Ну для начала, я не думаю, что «настоящий JS» вообще можно скомпилировать в натив ;) У тебя будет, скорей всего, какая-то часть интерпретируемая и какая-то компилируемая. Просто по стандарту языка.

Для Java в GraalVM (SVM, Native-Image) просто сказали, что мы не сможем так писать на «настоящей Java», мы будем писать на джава-подобном языке с огромными ограничениями. И это камень преткновения, потому что если ты разрабатываешь на обычной Java и только для прода компилируешь под Native-Image в экзешник, то вступают в силу все эти ограничения, и зачастую людям приходится переписывать свой код, потому что они недостаточно хорошо держали в голове эти ограничения.

Что касается перформанса, то тут трудно сказать. Скорей всего, компилируемая нода будет медленней тупо потому, что ты пишешь ее в 1 рыло, а V8 пишет толпа очень квалифицированных программистов гугла, которые могут чуть ли не на ассемблере вылизывать её для конкретных случаев. Грубо говоря, в GraalVM тоже есть свой интерпретатор JS, и хотя он тоже очень неплох, в некоторых тестах он сливает V8 подчистую, например в тестах на регулярные выражения, там в V8 прямо произведение искусства понаписано.

Если же представить, что допустим вы пишете одинаковыми силами, то тут уже возникают теоретические вопросы, да. Например гляди, в V8 никогда не JIT-компилируются методы, у которых больше 3 параметров в функции, или больше пяти, уже не помню. Если хочешь сделать функцию, которая тормозит на V8 - просто сделай ей побольше параметров, JIT ее не тронет и она будет там как кость в горле. А не трогает он её именно из-за того, что для специализации и частичной компиляции метода под разные параметры нужно потратить слишком много кодкэша. Условно говоря, метод которому на вход постоянно приходят три инта, и метод которому на вход приходит три строки - должны компилироваться радикально разными способами. Теперь представь метод, у которого постоянно меняются типы входных параметров - иногда это инты, а иногда строки, а иногда что-то ещё. Тебе нужно перебрать и скомпилировать все возможные частичные спецализации. Это тупо комбинаторный взрыв, если делать по-простому. (По сложному сделано в фреймворке Truffle из GraalVM, на котором написан Graal.js, он справится и с более чем тремя, но там очень сложный способ, я его не объясню в этом комментарии). Чтобы не иметь с этим дела, чуваки из Гугла просто не компилируют ничего, где много параметров. Для маленького количества параметров они начинают выводить «временные типы» скорей всего, я бы так сделал, но это надо уже копаться в доках на TurboFan/Ignition чтобы понять как по-настоящему. Но вот проблема, методы с большим количеством параметров и методы с переменными типами в JS - это норма, так все делают. И тебе придётся компилировать их по-честному. И либо тебе придётся брать сразу самый обобщённый вариант (и это будет очевидно всегда медленней, чем частичная специализация - два произвольных объекта сильно сложней сложить, чем два инта), либо устраивать комбинаторный взрыв и компилировать вечно. В целом, твой «компилируемый V8» будет на таких методах работать всегда менее удовлетворительно для пользователя, чем JIT по методам с короткой сигнатурой.

Короче, это можно очень долго теоретизировать, попробуй написать что-нибудь сам и посмотреть на результаты, погоняв какие-то синтетические тесты вроде моего [Carbon](https://github.com/graalvm-community/graalvm-carbon) (это гугловый Octane, перепакованный в один файл, чтобы легко запускать на Ноде). Кажется, это хорошая тема для мастерского тезиса или что-то такое, если ты найдёшь какую-то достаточно интересную тему чтобы проверить. Если вдруг будешь такое делать, то очень советую читнуть работы по GraalVM за авторством Вертингера и ко, он начинался точно так же, они делали универсальный фреймворк для интерпретации на примере JS движка.