Как стать автором
Обновить

Почему я скептично отношусь к переписыванию JS-инструментов на «быстрых» языках

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров17K
Всего голосов 58: ↑55 и ↓3+76
Комментарии50

Комментарии 50

Почему-то говоря о производительности в подобных статьях упоминают только процессорное время. Тем временем чаще всего смена JS на перечисленное (Zig, Rust, C/C++,...) даёт наибольший выигрыш по памяти.

Мне показалось, что Вы не поняли автора. Автор говорил о том, что программисты JS кода, до конца не понимают как использовать инструмент, которы! они используют.

Инструмент, потенциал которого, в силу общей слабости JS комьюнити, до сих пор не раскрыт и имеет большой потенциал. С чем лично я, более чем согласен.

По мне так это имеет смысл уже ради одной только возможности не связываться с инфраструктурой npm вне разрабатываемого кода. То есть с тем что во фронтэнд проект надёргается куча непроверенного кода из интернета ещё может и можно смириться, но запускать таковой код под своим пользователем чтобы это собирать и линтить - дикость.

Я в других экосистемах плохо разбираюсь, но как работают линтеры/сборщики в других системах? Для запуска линтера для других языков не нужно его скачивать из интернета и исполнять его на своей машине? Я без иронии, правда интересно :)

Либо как стендэлон приложения одного источника (компиляторы почти всего из мира компилируемого, инструменты для стат анализа кода или билда). Тут скорее речь, про кучу ненадежных зависимостей, которые нужны чтобы работать с npm пакетами. Не так давно в одном проекте встретил зависимость от другого проекта, с функционалом в 1 строку полезного кода

Ставятся из системного репозитория как любой другой софт.

Раскроете мысль как это защищает вас от запуска стороннего кода из интернета на своей машине? Я не защищаю npm и знаю о сотнях malware, которые случайным образом попадают на машину из-за огромного графа зависимостей и повсеместно используемых «крышечек» ^.

Но вот я захожу в первый попавшийся репозиторий rust, вижу зависимости, вижу build.rs, который исполняется без какого либо sandbox окружения и не понимаю почему это не запуск стороннего кода и не дикость

Да никак. Rust подвержен supply chain атакам так же как и JS.

Есть даже вот такие интересные мысли о необходимости создания extended standart library чтобы избежать такого количества фундаментальных зависимостей.

Здесь ещё вопрос в стоимости разработчика. На разницу месячной зарплаты между JS/TS и Golang разработчиками зачастую можно купить не самый плохой сервер, который, в подавляющем большинстве случаев, даже и не понадобится, или все будет упираться в БД, очередь сообщений и т.д.

Не очень понятно, у кого из них зарплата больше. Вроде по грейдам должна быть приблизительно одинаковая.

Я думаю, те зарплаты придётся не сравнивать, а складывать. Потому что найти гошника, который хорошо знает экосистему фронтенда очень тяжело. Соответственно, при нём должен быть ещё кто-то типа персонального лида-аналитика-ревьюера.

Я такой ;) Но чего-то особого спроса не наблюдаю. И так как сильно меньше матерюсь, когда в окне вижу го, то позиционируюсь дальше на него.

Дело в компаниях, которые используют ту или иную технологию. Часто на Node.js пишут от безысходности, когда что-то написать на другом языке в приемлемый срок просто невозможно, или когда программисты способны писать только на JS. Соответственно язык зачастую выбирают не самые лучшие компании с не самыми хорошими условиями. Плюс есть определенная стигматизация в IT сообществе: бэкенд разработчики часто в целом презирают JS/TS и к попыткам использовать эти языки в родной среде относятся негативно. В итоге у Node.js разработчика не сильно большой выбор. По моим ощущениям обычно требуется middle-fullstack за 100к-150к.

Middle fullstack за 100к-150к? Это было актуально лет 10 назад, сейчас цифры в 2 раза больше.

Разработчик на Go/Rust и.т.п. пишет код, который используется кучей других людей. Таким образом, ресурсы, затраченные единожды на разработку либы/cli-инструмента с лихвой покрываются экономией всех тех, кто их использует

Признавайтесь, кто баловался с JIT & WebAssembly?

Хотелось бы посмотреть реальные кейсы.

А как ? Там кстати есть проблема того что при динамической сборке схемы нельзя у инпутов указать deprecated

по скорости насколько выиграли? или по памяти

недавно скомпилировал парсер sql из сорцов постгреса в wasm, чтобы в js можно было разделять sql скрипт на отдельные запросы. Это оказалось более подьемная задача чем портировать все это на js

Валидировали огромные excel файлы на клиенте с помощью wasm. Был выигрыш хотя бы в том, что js библиотекам чтобы получить первую строчку нужно было почему то парсить весь файл. Плюс сам парсинг был быстрее. Плюс экономия сервера и на времени сетевых запросов.

И ни слова о том, что интерпретируемые языки всегда медленнее компилируемых.

Немного бред несёшь, js уже сто лет как интерпретируемо-компилируемый, так что иди почитай матчасть

интерпретируемо-компилируемый

Лол, это же всё равно априори медленнее, чем полностью компилируемый язык. И ещё матчасть учить отправляют. Ну-ну)))

Почему медленее? Только запуск и первые запросы будут медленее пока JIT не прожарит исходники а нейтив. Дальше работает уже машинный байткод.

Вот потому и медленнее, что есть всякие только. Не будем забывать про всякие CI/CD системы, где поднимается докер образ для сборки бандла, а после сборки образ удаляется. То есть код выполняется всего один раз. Тот самый раз, который медленный. И это по итогу влетает в копеечку за оплату облачных сервисов.

Вы правы. Это действительно копеечка.

Что там с эффективностью использования кэша JSом в 2024 году?

Пол века инженеры всей планеты занимались микрооптимизациями всяких бранч предикторов, компиляторов и другими вещами чтобы повысить эффективность работы программ с кэшем процессора... По пути кучу раз облажались и насовали критических аппаратных уязвимостей в погоне за оптимизациями... Чтобы одним из главных языков в мире стал JS.

При холодром старте, подготовка js кода может занимать больше 100% времени используемошо на его исполнение. Специфика языка.

Как следствие - кеширование как минимум, а способность управлять тем что и как кешируется/компилируется - как максимум, один из золотых граалей старта приложения.

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

Но так как у JS сейчас чуть ли лучший JIT в мире, это сильно смягчено.

Проблема не в том, что JS изначально был интерпретатором. Это как раз решаемо, так как компилировать можно и на лету. Причем не только кешируя результат, но еще и оптимизируя его в зависимости от профиля нагрузки.

Проблема производительности JS в динамической типизации и сборке мусора. Первое в любом случае приводит к дополнительной нагрузке на процессор и память при исполнении кода. А второе может приводить к непредсказуемым задержкам в неподходящий момент времени и/или к излишнему потреблению памяти.

Так как кеш CPU не резиновый, то бОльшее потребление памяти напрямую влияет на производительность.

Вторая проблема JS, которая органически вытекает из всего перечисленного выше - это необходимость в собственной среде выполнения. Иными словами, если код на том же Rust может почти из издержек многократно вызываться из любой среды, хоть из драйвера в ядре, то код на JS так просто не вызвать из-за необходимости инициализации среды. И это заметно сужает область его применения.

Потому что железо позволяет вот и скептично. Запустить браузер на одноплатнике уже страдание. Фаза экстенсивного роста закончилась, теперь чтобы продолжать развитие надо занимать интенсивным развитием. Выжимать все соки из очевидно менее эффективного языка кажется не слишком рациональным.

Я вот на питоне перешел на uv с ruff и чую как мои волосы стали мягкими и шелковистыми. И это реальный прорыв в DX что со мной произошел за последние несколько лет.

И когда я смотрю на то как вебпка сборки нашего фронта идут по 5-10 минут мне становится очень грустно и печально. Особенно когда вижу насколько быстрее работает bun и всякие swc с esbuild на моих петах. И мне как-то пофигу что я не могу эти тулзы поправить (на самом деле могу я go и rust знаю лучше js c ts) я их все равно за всю карьеру не патчил ни разу, как и 95% пользователей.

Первое, что я делаю, когда я вливаюсь в новый проект -- это переписываю билд-процесс с вебпака на esbuild. И всем становится хорошо )

А что, собственно, происходит? Как я понял, под предлогом ускорения инструменты написанные на JavaScript переписываются на других языках. Зачем? Не так велико ускорение чтобы его можно было считать причиной. Тогда зачем? Есть логические возможности…

  • обойти костность сообществ инструментов, переписывают чтобы сделать то, что не желают сделать на JavaScript

  • переписывание ради переписывания - про инструментарий JS не очень в курсе, но эпидемия переписывания на Rust (cat -> bat, mc -> nnn, node.js -> Tauri…) отлично рекламирует Rust, да и подводит к предыдущему пункту

  • переписывание ради ущемления JavaScript, он может тупо мешать, об этом ниже

JavaScript движется в сторону JIT компиляции, а индустрия - в противоположную сторону, к W^X политике. Это плохо дважды - возможность применить JavaScript подрывает цели W^X политики, это раз, а когда обнаружится конфликт W^X и JIT - это лишнее недоумение, это два. И ведь это никак не домыслы, уже MIT, если правильно помню, диалект Scheme не планирует появляться на современных macOS - там тоже W^X. В Termux, которого самого постепенно выпиливают с Андроид, Racket есть, а Julia уже нет. И т.д. и т.п., лягушку варят не спеша.

JavaScript представляет Web, а взаимоотношения Web с нативом… чисто для полноты решил упомянуть.

Так что же происходит? ИМХО, конфликт интересов реализуется в действиях.

Я бы не сказал, что ускорение в 35-70 раз не так велико. Чем больше проект -- тем более ощутим выигрыш от использования быстрых инструментов.

(cat -> bat, mc -> nnn, node.js -> Tauri…)

Только nnn не является "переписыванием" mc, а Tauri вообще никакого отношения не имеет к NodeJS

А мне кажется - является. А Tauri вообще переписанный Node + переписанные кусочки превращающие Node в Electron и Ionic.

Тем не менее я сомневаюсь, что JS медлителен от природы, или что мы исчерпали все возможности его улучшения.

Вообще странно слышать подобное, учитывая, что JS именно медлителен от природы), а то, что имеем сейчас с JIT и подобным, это именно попытка ускорить и выжать из него больше.

При этом как-то в статье не упоминается, что JS-приложения как-то неприлично много потребляют ОЗУ :( Вероятно, что даже среда разработчиков под JS-инфраструктуру ломанулась переписывать всё на Rust/любой другой язык именно из-за этого.

В целом читается так, будто это грусть JS-разработчика, который рассчитывал, что, выучив один язык, ему этого хватит для всего, но разочарование, что инфраструктурные проекты для языка пишутся на других, — понимаемо.

Как по мне странно что разработчики движка не хотят выпилить cjs модели, отставив чисто esm, ибо тогда чисто физически анализировать и собирать код было бы проще

К тому же куче я считаю странным что тс все ещё не находится в движке. Ибо по факту он стал стандартом. Причем таким нехитрым образом можно было бы проверки типов в рантайм

Вот тогда бы зажили)

К тому же куче я считаю странным что тс все ещё не находится в движке. Ибо по факту он стал стандартом.

По факту он стал стандартом разработки, но сам язык не стандартизован. Далее, поскольку нодовский движок — это V8, то нужно, чтобы имплементацией Тайпскрипта занялся Гугл. Однако поскольку V8, в первую очередь, — браузерный движок, то нужно обеспечить ещё и интеграцию со стандартом HTML.

Таким образом, у Гугла должна быть мотивация вложить кучу денег в имплементацию Тайпскрипта. Но без явных спецификаций успеть за Майкрософтом будет очень сложно. Отсутствие поддержки в движках от Мозиллы и Эппла также будет препятствовать проекту, тем более, что самому Гуглу Node.js не очень интересен.

Причем таким нехитрым образом можно было бы проверки типов в рантайм

нехитрым?

Так я понимаю что большинство того что я сказал это прям утопия. Но в целом очень хотелось бы нативного тса, ибо даже всякие баны и дено понимают что ну никуда без них

По поводу спек и саппорта тоже согласен, но тут можно намекнуть на WECG, и к примеру потратить годик на стандарты

нехитрым?

Звучит странно, но если так подумать, то много ли вещей в разработке движка можно назвать нехитрыми. Там как будто все непросто, но по сравнению со всем это звучит нехитро

Прежде всего надо начинать с оптимизацией приложения, архитектуры. А потом уже играться с разными вещами. А то большинство приложений имеют баги и утечки памяти, о которых они не знают.

Єто ошибка потому, что выбрав оптимальную архитектуру, вы, как человек который не знает систему, так и не поймете почему она тормозит.

А тормозить она будет из-за невозможности оптимизировать ваш код Агентом, который пришел в восхищение от вашей архитектуры и читаемости кода.

По мне так наоборот, переписывание с JS на компилируемые языки - это позитивный тренд. Все же, редко кто-то переписсывает вещи, которыми никто не пользуется, а переписывание широко используемых вещей позволит сильно сократить потребление ресурсов у многих пользователей.

Статья выглядит, как плач автора о том, как же ему не хочется выглядывать за пределы своего уютного JS-мирка.

Но ведь в конечном счете, от такого переписывания js-разработчики только выигрыват: используя компилируемые библиотеки, можно писать на js более производительный код теми же усилиями.

Во-первых, есть вышеупомянутые доступные возможности, поскольку экосистема JS-инструментов достаточно долго фокусировалась на создании чего-то просто рабочего, а не чего-то быстрого.

Впрочем, если автор ратует за написание более производительного кода на js, то, может, было бы более конструктивно призвать js-коммьюнити писать не просто рабочий, но и производительный код, использующий все возможнлсти js по увеличению производительности? Тогда и поводов для переписывания на другие языки будет меньше. А конечные пользователи будут только выигрыше, ибо тормоза веба не нравятся никому.

Смотрел интервью с biomeJs он там сказал что основной буст получил изо того что просто выполняет все в максимально доступном числе потоков js так тоже может но в линтере этого нет. Второй буст в том что используется общее ast для разных инструментов я думаю в js тоже можно сделать такую оптимизацию

Если кто-то переписывает что-то с js на другие языки, то нужно быть совсем дурачком, чтобы думать что они занимаются этим от нечего делать. Программисты по своему главному правилу обычно не трогают то, что работает, а если доходит до того, что трогают, значит это "что-то" работает слишком отвратно.

По своему опыту с биржами - то, что сейчас реализовано через сайт, через десктопное приложение работало бы в десятки раз меньше потребляя память, в десятки раз менее нагружая процессор и десятки/сотни раз имея меньше глюков. Типичный пример - "десктопный" терминал Binance (как это модно сейчас на базе браузера), - когда я его запустил в первый раз, то удивился наличию кнопки "Обновить", через пару недель я понял, что без этой кнопки там работать просто невозможно. А так - страницы в хроме отжирающие по 4 Гб оперативки, грузящие по 2 потока на 100% (на i5 13600к), зависающие, с пропаданием получения данных - это становится массовым явлением, хотя с точки зрения выполняемой работы они делают меньше чем старый терминал Quik на Celeron 433, который работал просто на голову стабильней и быстрее.


Единственное что радует - сейчас практически везде есть api, используя который, можно делать быстрые приложения на нормальном языке.

Я как то отговорил товарищей переписывать nodejs на go, просто рассказав что nodejs нужно запускать в многопоточном режиме, чего они не знали и удивлялись как медленно работает один поток на 16 ядрах. И кто теперь дурачок?

Благодаря переписыванию на компилируемые языки можно часть API сделать не расширяемым и таки заставить платить самых хитрых.

В этом году в эту сторону пошёл тулинг для монореп Nx. Под песни про скорость раста они сейчас депрекейтнули и скоро выпилят возможность подставлять плагины для кастомного облачного кеширования результатов выполнения команд. Хочешь кешировать в закрытой инфре? Занеси денежку, у нас есть пепяка на расте для этого. При этом раньше возможность реализовать своё кеширование представлялась как одно из преимуществ Nx прям у них в доке.

Тред в nx https://github.com/nrwl/nx/issues/28434

О это прям про нас, прошлый тех лид "возбудился" от Rust, я был на других проектах, поэтому не придал внимания этой "болезни", теперь тех лид ушел, сейчас ворох проблем:

  • Хреновый уровень архитектуры и понимания nodeJs, который привел к тому что NodeJs не работает как надо, worked thread проигнорированы, попытки сделать многопоточность в одном потоке через async/await, использования поиска в массиве вместо поиска по словарю и прочая лютая дичь.

    • Теперь ситуация такова: переписывание этого "корявого" приложения на Rust даёт мощный прирост производительности, но стоит потратить несколько часов на оптимизацию исходного кода на JS, и отрыв уже не такой значительный. И возникает логичный вопрос: а зачем вообще переписывать тогда? Но маховик был уже запущен и огромное количество ресурсов ушло на переписывание.

    • Как обычно, дело не в языке, а в архитектуре. Большинство проблем с производительностью возникают из-за недостатков именно архитектуры или понимания технического стека.

  • На уровне бэкенда нам далеко не всегда нужна «CPU-молотилка». Множество задач сводится к "получить данные, слегка обработать и отправить дальше", а основное время уходит на ожидание I/O операций. В таких случаях переписывание на Rust не всегда даёт значительный прирост производительности.

  • Основное ядро разработчиков хочет переписывать на Rust просто потому что полюбили язык.

    • Большинство времени разработчики просто переписывают код 1 в 1, а иногда даже хуже. Сложилось мнение, что раз Rust — суперязык, значит любой написанный на нём код априори будет суперэффективным. Очень много примеров где код становился медленнее.

    • К сожалению приходится за ними следить, чтобы не начали писать как на C, код очень просто может стать очень сложным на ровном месте, использование бесконечных циклов обычное дело, могут вставить хинты для процессора где не надо. Иногда прям реально дежавю от С++ и вспоминаешь о всех этих книгах про чистый код.

  • Приводит к куче бесполезных обсуждений "давайте rust и для ML юзать, вместо python". Дай волю и простые shell скрипты на Rust перепишут.

В итоге решили остановить хаотичное переписывание и переписывать Rust только там, где это действительно необходимо и с учетом roadmap. Новая логика идет на Rust.

Язык то хороший, но вот этот юношеский максимализм "все должно быть на Rust" немного поднадоел, из каждого утюга. Мне кажется разработчики читают статьи от разработчиков библиотек и решают, что это золотая пуля для всего.

По мне, Rust всё равно слишком низкоуровневый для повседневных "скучных" бизнес-задач, но это уже вкусовщина думаю.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий