[txiki.js - 작고 강력한 JavaScript 런타임

txiki.js는 QuickJS-ng를 JS엔진으로, libuv를 플랫폼 계층으로 사용하여 고성능 비동기 I/O를 제공하는 작은 JavaScript 런타임입니다. 최신 ECMAScript 표준 및 WinterTC 호환을 목표로 하며, Web Platform API, 네트워크 기능, 시스템 수준 기능, 다양한 내장 모듈을 지원합니다. C 기반으로 작성되어 빠른 실행 속도와 낮은 메모리 사용량을 제공하며, GNU/Linux, macOS, Windows, 기타 Unix 계열 시스템에서 동작합니다.

https://news.hada.io/topic?id=27294

#javascript #runtime #quickjs #libuv #webplatform

txiki.js - 작고 강력한 JavaScript 런타임 | GeekNews

최신 ECMAScript 표준 및 WinterTC 호환 을 목표로 함QuickJS-ng 를 JS엔진으로, libuv 를 플랫폼 계층으로 사용해 고성능 비동기 I/O 제공Web Platform API 지원: fetch, WebSocket, Console, setTimeout, Crypto, Web Workers 등 포함네트워크 기능 내장: TCP, UDP,

GeekNews
@mdhughes since when and how so? all I'm aware of is #swish, which runs in a single OS thread and uses #libuv for async io (same as Node.js I believe)
🌘 以 C 語言從頭打造 JavaScript 運行環境:Jade Runtime
➤ 循序漸進:使用 C、JavaScriptCore 與 libuv 建構 Jade Runtime
https://devlogs.xyz/blog/building-a-javaScript-runtime
本文深入介紹如何利用 C 語言從零開始建構一個極簡的 JavaScript 運行環境,名為 Jade Runtime。作者透過整合 JavaScriptCore 作為 JavaScript 引擎,以及 libuv 處理非同步 I/O 和事件循環,詳細闡述了現代運行環境如何將 JavaScript 程式碼與系統底層操作連結,包括事件循環的實現機制,以及如何將原生 API 暴露給 JavaScript 使用。這對於理解 Node.js、Bun 和 Deno 等運行環境的內部工作原理至關重要。
+ 太棒了!這篇文章詳細解釋了運行環境的底層架構,讓我對 JavaScript 的執行過程有了更
#程式設計 #JavaScript #C 語言 #運行環境 #JavaScriptCore #libuv
devlogs

Your source for developer logs, guides, tutorials, and insights.

Huh, either #LibUV’s `fs_stat`, or #Lua’s `os.time`, or both, exhibit different behaviour in my personal Mac (obsolete) and my work Mac (now vintage) 🧐
Пример типичной системно-прикладной разработки, реализация своей «очереди сообщений» (event loop).
Использованием
#epoll, вместо «традиционных» select & poll, для асинхронной работы через polling’а (и мультиплексирования).

Отслеживание файловых дескрипторов через
#epoll выглядит более современно, меньше копирования памяти между user space и kernel space. А при появлении ожидаемых данных можно напрямую переходить к объекту или структуре данных, что важно при наблюдении за несколькими файлами и\или соединениями. Устраняется поиск «сработавшего» файлового дескриптора в индексных массивах, полноценное О(1) во всех случаях. Можно сразу же работать с теми экземплярами объектов, которые оборачивают тот файл или udp-поток, tcp-, quic-соединение, где появились новые данные.

Есть несколько готовых к использованию «очередей сообщений» (event loop'ов) —
#libev, #libuv, #libevent. Для некоторых агент-серверные решений и брокера #RabbitMQ это подходит. Однако, в некоторых случаях AMQP-библиотеки не скрещиваются с уже готовыми «очередями сообщений». Потому что агентская часть может активно использовать асинхронно-реактивное программирование с хорошей и проверенной «горизонтальной масштабируемостью». Т.е. на агентской части выполняется много работы и реализация сделана через sharing nothing многопоточность. Это такая парадигма, когда не просто достигается не только горизонтальная масштабируемость через lock-free\wait-free, а так же исключается много вредного, как тот же cache ping-pong или false sharing. Внутри агентов идёт своё управление потоками с выделениями памяти. Не только в плане «динамической памяти» (heap, аллокаторы а-ля #jemalloc от #Facebook), но и приколами вокруг pinning страниц, учёта #NUMA и даже huge pages(меньше промахов в #TLB).

Почему бы не использовать epoll?
Библиотека не обязана вычитывает данные целиком из потока (сокета), а может забирает данные лишь до тех пор, пока не насытится автомат состояний (finite-state machine). Например, выполняется парсинг сущностей AMQP-протокола, которые, по мере накопления, передаются в обработчики указанные клиентом библиотеки.
И это плохо соотносится с тем, что используя
#epoll надо выбирать какой вариант оповещений использовать:
• «по уровню» (level-triggered),
• «по фронту» (edge-triggered).

Особенности поведения отдельно взятой библиотеки может не позволять использовать работу «по фронту» (edge-triggered), т.к. библиотека не вычитывает полностью все данные из файловых дескрипторов.

Можно быть хоть пять раз technical lead и всё это прекрасно знать, но следует помнить, что как только в коде появляется флаг EPOLLET, то необходимо проводить аудит работы с потоками данных. Это избавляет команду от многих заморочек вокруг тестирования и ковыряния с каким-то совершенно непонятным поведением кода.

Про
«Edge Triggered Vs Level Triggered interrupts»

#programming #linux #softdev #трудовыебудни
Edge Triggered Vs Level Triggered interrupts

Discussion: Level triggered: as long as the IRQ line is asserted, you get an interrupt request. When you serve the interrupt and return, ...

К вопросу использования #epoll вместо хорошо знакомых и «традиционных» select & poll. Т.е. асинхронной работы с чем-либо посредством polling’а и мультиплексирования.

Недавно пришлось заниматься реализацией очереди событий для AMQP-CPP. В одном из продуктов решено сделать связь агентских частей с основным «контроллером» через #AMQP, в качестве брокера #RabbitMQ (всё стандартно, обычный кластер и TLS-соединения).

Вот только агенты продукта активно используют асинхронно-реактивное программирование с хорошей «горизонтальной масштабируемостью». Когда достигнуто полноценное sharing nothing, не просто горизонтальная масштабируемость через lock-free или wait-free и закон Амдала. Исключается много всего и сразу, как старый-добрый cache ping-pong, так и печаль с false sharing.

Отсюда внутри агентов и своё управление потоками с выделениями памяти. Не только в плане heap (динамической памяти, со своими аллокаторами а-ля #jemalloc от #Facebook), но и приколы вокруг узлов #NUMA и даже huge pages (снижающих «давление» на #TLB, меньше промахов).

Первая же проблема выплыла почти сразу — не реально использовать библиотеку AMQP-CPP с уже предоставляющейся поддержкой #libev, #libuv, #libevent. Несовместимы эти очереди сообщений с имеющейся моделью управления потоками и организации задач на агентах.

Почему был взят epoll

Подход используемый в #epoll выглядит более современно, меньше копирований памяти между user space и kernel space. А при появлении данных в отслеживаемом файловом дескрипторе можно напрямую перейти по указателю на объект класса или структуру данных. Тем самым обходиться без поиска дескриптора по индексным массивам/контейнерам. Сразу же работать с экземплярами объектов оборачивающих нужное #tcp -соединение, того самого, в которое и пришли данные.

И тут обозначилась вторая проблема, что используема AMQP-библиотека не вычитывает данные целиком из потока сокета. Например, забирает данные лишь до тех пор, пока не насытится автомат состояний (finite-state machine), выполняющий парсинг сущностей AMQP-протокола.

Используя #epoll приходится выбирать на какой вариант обработки событий ориентироваться:

  • срабатывание оповещений «по уровню» (level-triggered),
  • выбрасывания событий «по фронту» (edge-triggered).

И беда с библиотекой в очередной раз показала, что нельзя использовать работу «по фронту» (edge-triggered) не изучив досконально работу подсистемы отвечающей за вычитывание данных из файловых дескрипторов. И появление флага EPOLLET в коде является маркером, о том, чтобы проводить аудит использовавшихся решений.

Про Edge Triggered Vs Level Triggered interrupts можно почитать в https://venkateshabbarapu.blogspot.com/2013/03/edge-triggered-vs-level-triggered.html)

#programming #linux #трудовыебудни

Akkoma

At a very basic core level, a comparison between @deno_land 2.0 and @nodejs could probably be summarised as:

- JS-runtime: Both uses V8
- Asynchronous I/O: Node.js uses #libuv, Deno uses #tokiors
- Native code: Node.js uses C++, Deno uses Rust

So essentially it boils down to libuv vs tokio and C++ vs rust

If one ignore everything else about Node.js and Deno, the winner is clear to me.

Красно-черные сигналы в node.js

Что происходит, когда мы отправляем сигнал приложению на node.js? Когда вызываются обработчики? А где хранятся? Во всем этом мы разберемся в данной статье, начиная от пользовательского кода на javascript и до встречи с операционной системой.

https://habr.com/ru/articles/840108/

#javascript #nodejs #libuv #красночерное_дерево #epoll #linux #сигналы

Красно-черные сигналы в node.js

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

Хабр

Куча таймеров в node.js

А знаете ли вы, как на самом деле работают таймеры в node.js? В этой статье мы разберемся, как хранятся таймеры, когда запускаются и как в целом все работает вплоть до системных вызовов.

https://habr.com/ru/articles/830644/

#javascript #nodejs #libuv #куча #очередь #epoll #linux #таймеры

Куча таймеров в node.js

Приветствую вас, читатели этой статьи! Мне с давних пор нравится язык javascript. Считается, что это язык с низким порогом входа, но, несмотря на это, если приглядеться, можно найти много интересного...

Хабр

Funsies: node-gyp is broken on latest kernel.

Likely some other libuv stuff as well. In case you're experiencing more weirdness than usual, consider a downgrade 

https://github.com/nodejs/node/issues/53051

#nodejs #linux #libuv

Node 22 node-gyp build fails "Text file busy" · Issue #53051 · nodejs/node

Version v22.0.0 Platform Linux laharl 6.9.1-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 17 May 2024 16:56:38 +0000 x86_64 GNU/Linux Subsystem node-gyp What steps will reproduce the bug? Attempted to build ...

GitHub