Разбор интервью с автором TypeScript о портировании его на Go
- четверг, 13 марта 2025 г. в 00:00:12
Анонсирован порт TypeScript на Go, который показывает двухкратное уменьшение использования памяти и десятикратное улучшение скорости работы!
В этой статье мы разберем в деталях часовое интервью с автором TypeScript Андерсом Хейлсбергом об этом портировании.
Чего не хватает для лучшей производительности node.js?
Официальный анонс: https://devblogs.microsoft.com/typescript/typescript-native-port/.
Исходный код: https://github.com/microsoft/typescript-go.
Далее, мои (https://t.me/artalog) заметки и комментарии по интервью.
Улучшение перформанса TS — основной фича-реквест в комьюнити, о нем говорят чаще, чем о запросе новых функций.
Переписывание 80% функционала (на момент анонса) заняло полгода (началось в августе 2024). Например, еще не поддерживаются JSDoc, JSX и еще несколько вещей. И дошлифовать остальные 20% займет еще пару лет. Это важно для больших существующих продуктов, но новые проекты или проекты без использования каких-то менее популярных фич TS смогут использовать новый компилятор уже до конца года!
Как раз во время публикации этой статьи Андерс высказался подробным текстом на этот счет: https://github.com/microsoft/typescript-go/discussions/411#discussioncomment-12466988
Переписывать с нуля такой большой проект нереально, решено было портировать код файл за файлом с минимальными отличиями. Важной целью стояло сохранение "99.999%" поведения существующей версии для надежной миграции продуктовых команд.
Go оказался наилучшим вариантом для порта по ряду факторов:
он достаточно низкоуровневый и в целом всегда дизайнился под перф,
именно на него лучше всего ложится текущий код TS, который содержит огромное количество рекурсивных данных (это же отметает Rust),
он очень кроссплатформенный (это же отметает C#).
Текущий код TS написан в нормальном функциональном стиле, т.е. просто функции и структуры данных, преимущественно иммутабельные, никаких высокоуровневых ООП или ФП абстракций. Огромный лайк за это 🤓.
Иммутабельные структуры данных нужны, например, для быстрой и безопасной перезагрузки части кода во время его редактирования в IDE продуктовым разработчиком.
Поэтому многопоток на Go легко завелся, и x3 перфа пришло именно от этого. Стоит еще учитывать, что некоторые процессы все еще ограничены 4 тредами, а что-то еще не до конца распараллелено. Андерс об этом не заикается, но кажется, что текущие улучшения производительности — далеко не предел.
Впрочем, один из серьезных челленджей многопотока — уход от абьюза детерминированности синглтреда. Это очень интересный топик, я сам сталкивался частенько с тем, что некоторые архитектурные моменты или аспекты АПИ или структуры данных, не оптимальные в классическом понимании, могут не явно, но положительно влиять на производительность или "из коробки" давать некоторые преимущества. Самый наглядный пример — та же иммутабельность, она сама по своей природе является thread-safe. Но Андерс говорил про абьюз порядка инициализации загружаемых сущностей, детерминированный в сингтреде и непредсказуемый в многопотоке.
Негативный момент в том, что из-за поддержки многопотока кодовая база на Go расходится с оригиналом, чего команда всеми силами пытается избежать.
Еще x3 производительности дает использование структур, которые повышают скорость взаимодействия с памятью и значительно упрощают мультитред.
Андерс говорит, что полученное уменьшение потребления памяти важно не столько с точки зрения загрузки компьютера продуктового разработчика, сколько с точки зрения выполнения каждого конкретного процесса, т.к. позволяет меньше утыкаться в лимиты кеша процессора и реже ловить деоптимизации этого плана.
Здесь очень хочется высказать свою большую печаль в том, что TC39 вообще заморозили https://github.com/tc39/proposal-record-tuple и очень медленно прорабатывают https://github.com/tc39/proposal-structs. С ними как минимум x5 производительности можно было бы получить и на node.js.
Это большая и серьезная тема, по мнению автора этой статьи. В конце будет опрос на эту тему, поучаствуйте, пожалуйста. Я считаю, что нужно прикладывать больше сил в развитие производительности JS, потому что JIT может оптимизировать далеко не все, и авторам низкоуровневого высокопроизводительного кода очень не хватает, помимо структур, нативного хеширования и доступа к UID поинтера, встроенных более производительных структур данных, как unordered hashmap и intrusive linked list, и т.д.
Хотя, справедливости ради, Андерс говорит, что Go удобен и своей доступностью к числовым типам разной размерности, в то время как в JS есть только огромный number (и тут подвижек не предвидится).
Следующим серьезным челленджем Андерс называет API тайпскрипта. Кто-то может сказать, что его и нет вовсе, но через манкипатчинг в JS его все же как-то используют. Версия же на Go полностью убирает любые дыры. И радостная новость заключается в том, что из-за объективной необходимости экосистемы в модификации и коммуникации работы TS и благодаря значимому ускорению его работы, команда разработки будет сосредоточена в том числе и на разработке качественного публичного интерфейса для взаимодействия с внешним миром.
В том числе, это хороший толчок к разработке нормального LSP для TypeScript. Поддержка и корректная работа связанного тулинга тоже в фокусе.
Так же продумываются интеграции с LLM, что бы дать им лучше анализировать и понимать код, не пытаясь просто "читать" его, привнося больше гарантий и точности в работу LLM.
Может показаться, что уход от предметного и целевого языка программирования уменьшит количество сторонних контрибьютеров в TypeScript, но их в целом не такое большое количество. И Go здесь выступает в хорошем свете, потому что он намного дружелюбнее для JS разработчика, чем тот же Rust.
Вопрос на который я бы хотел получить ответ - это что делать с отсутствием dogfooding.
В любом случае, было озвучено что поддержка кодовой базы на TS возможна еще очень долгое время даже после полного перехода на Go-версию. А вся эта история звучало это как серьезный план, а не вариант результата эксперимента.
Очень интересное интервью, очень интересные и многогранные перспективы. Видно что миграция планируется очень плавная по всем направления и это так же радует.
Что ж, ждем результатов запуска DOOM на typescript-go.