Введение
Мы живём в третью эпоху JavaScript: частое стремление писать инструменты для JavaScript на Rust или ради производительности.
Но авторство таких инструментов — задача сложная, особенно на Rust. Я долго терпел поражения, изучая эти технологии, и хотел бы, чтобы другим не приходилось проходить тот же путь мучений.
Я хочу внести свой вклад в сообщество этим учебным материалом, чтобы вам не пришлось спотыкаться там же, где спотыкался я.
Разработчиков на стороне Rust немного — я был бы рад видеть здесь побольше людей и присоединиться к нам, чтобы вместе строить лучшие и более быстрые инструменты для всех.
Обзор
В этом материале применяются стандартные фазы компилятора (frontend):
Source Text --> Lexer --> Token --> Parser --> ASTНаписать парсер JavaScript относительно несложно: это на 10% архитектурные решения и на 90% кропотливая работа над мелочами.
Архитектура в основном влияет на две вещи:
- производительность парсера
- удобство потребления нашего AST
Если заранее знать варианты и компромиссы перед тем как писать парсер на Rust, весь путь станет намного спокойнее.
Производительность
Качественная программа на Rust — это меньше выделений памяти и меньше циклов CPU.
Почти очевидно, где что выделяется на куче: ищите Vec, Box, String и тому подобное. Понимание их использования даёт представление о скорости: чем больше аллокаций, тем программа медленнее.
Rust даёт возможность обходиться без накладных расходов на абстракции — не нужно бояться, что абстракции сами по себе убьют производительность. Следите за алгоритмической сложностью и, как правило, всё будет в порядке.
INFO
Стоит также прочитать The Rust Performance Book.
Исходный код Rust
Когда производительность вызова функции неочевидна, не бойтесь нажать кнопку «source» в документации Rust и читать сам код — часто он понятнее, чем кажется.
INFO
Переходя по коду Rust, поиск определения обычно сводится к fn function_name, struct struct_name, enum enum_name и т.д. Это плюс стабильного синтаксиса Rust (в отличие от JavaScript 😉).