Forwarded from Node.JS [ru] | Серверный JavaScript
Стратегии борьбы с throttle в event loop при работе с Native Addons и FFI через worker_threads
Node.js живёт на одном потоке — это знают все. Но когда в дело вступают Native Addons (napi, C++ модули) и FFI (Foreign Function Interface), event loop может неожиданно "зависнуть". Даже если ты используешь
FFI тут особенно неприятен. Библиотеки типа
Что с этим делать?
1. Вынос в dedicated worker.
Создаёшь отдельный worker, грузишь туда аддон, общаешься через
Внутри worker:
2. Асинхронные API для аддонов.
Если пишешь аддон сам — используй n-api async work (
3. Пул worker'ов с очередью.
Задачи распределяются, и один тяжёлый вызов не может монополизировать все ресурсы. Стандартный паттерн — берёшь задачу из очереди, отдаёшь свободному воркеру.
4. Atomics и SharedArrayBuffer.
Блокировка без захвата event loop. Но требует поддержки
5. Мониторинг.
Замеряй время вызовов через
Коротко:
-
- Для своих аддонов — async n-api.
- Для FFI — пулы и очереди.
Вывод:
Изоляция нативных вызовов через worker_threads с асинхронными API и мониторингом — единственный способ избежать throttling event loop в production.
Node.js живёт на одном потоке — это знают все. Но когда в дело вступают Native Addons (napi, C++ модули) и FFI (Foreign Function Interface), event loop может неожиданно "зависнуть". Даже если ты используешь
worker_threads, throttle всё равно случается. Почему? Потому что нативные вызовы не всегда изолируются полностью. Блокирующий системный вызов в аддоне может зацепить libuv thread pool или V8, и основной поток начинает тормозить.FFI тут особенно неприятен. Библиотеки типа
ffi-napi или koffi вызывают shared library синхронно — event loop просто стоит и ждёт, пока вызов вернётся. Все остальные задачи замораживаются.Что с этим делать?
1. Вынос в dedicated worker.
Создаёшь отдельный worker, грузишь туда аддон, общаешься через
MessageChannel. Главное — не передавай shared memory без синхронизации, если аддон не thread-safe.const { Worker } = require('worker_threads');
const worker = new Worker('./native-worker.js', { workerData: {} });
worker.postMessage({ task: 'heavyCalc', data: [1, 2, 3] });
worker.on('message', result => console.log('Результат:', result));Внутри worker:
const { parentPort } = require('worker_threads');
const nativeAddon = require('native-addon');
parentPort.on('message', msg => {
const result = nativeAddon.heavySync(msg.data);
parentPort.postMessage(result);
});2. Асинхронные API для аддонов.
Если пишешь аддон сам — используй n-api async work (
napi_create_async_work). Для FFI — заворачивай вызовы в setImmediate или setTimeout с нулевой задержкой. Это даёт event loop шанс обработать другие задачи.3. Пул worker'ов с очередью.
Задачи распределяются, и один тяжёлый вызов не может монополизировать все ресурсы. Стандартный паттерн — берёшь задачу из очереди, отдаёшь свободному воркеру.
4. Atomics и SharedArrayBuffer.
Блокировка без захвата event loop. Но требует поддержки
SharedArrayBuffer и аккуратной реализации.5. Мониторинг.
Замеряй время вызовов через
process.hrtime.bigint() или performance.now(). Если вызов длится дольше 50ms — это красный флаг. Логируй и переключай на worker.Коротко:
-
worker_threads — база, но не панацея.- Для своих аддонов — async n-api.
- Для FFI — пулы и очереди.
Вывод:
Изоляция нативных вызовов через worker_threads с асинхронными API и мониторингом — единственный способ избежать throttling event loop в production.
Forwarded from ai.dot(ufna, dev)
Индустриальные обсуждения во многих чатиках выглядят именно так.
Независимо от темы обсуждения.
Независимо от темы обсуждения.
Forwarded from Andrey
Если чуть пролить аналитику, то длинный ответ будет такой:
Из железа у тебя прям щас есть выбор из:
1. Малый компьют с дохера объёма (370/395/спарки/макбуки/мини/студио/нэйм ит);
2. Средний компьют с мало объёма (3090/4090/b60/b70/7900/9700/нэйм ит);
3. Толстый компьют с дохера объёма (PRO6000/A100/H100/H200/MI250/нэйм ит).
Что отсутствует? Всё верно - средний компьют с дохера объема. Условно говоря, что-то типа RTX4090 на 64гб за недорого. На рынке ровно ничего подобного нет. И вот это довольно интересный момент, потому что РОВНО ТАКАЯ железка всем и нужна в массовом секторе имхо. В какой-то степени я даже удивлён, что всё ещё никто ничего подобного не предлагает, потому что отрывали бы с руками кмк.
Докидываем сюда мультипликатор веселья в виде охуевших цен не разное и всё становится ещё интереснее.
Но допустим, что такая железка у нас есть. Вопрос теперь не менее интересный: а что в неё грузить?
Если говорить про квантованные модели, то у тебя есть:
1. Квен/гемини 27B/31B под 24-32Гб;
2. Целый ворох устаревших на 3-4 поколения моделей типа 70B/120b для 48-64гб;
3. Весь прочий жир типа 0.3T-1T++ моделей, для чего надо 250-300++ Гб.
Что отсутствует? Всё верно - что-то между 2 и 3. Тупо нет и пока не предвидится хороших, качественных моделек такого объёма. Условно говоря, у тебя до сих пор нет какого-нибудь "Qwen 3.6 Coder Next", который при своих 80B как раз влезал в 48 гиговые карточки. То есть, условная 120-ка должна без проблем влезать в 64гб. Но такой модельки сука нет, а всё остальное в подобном типоразмере - либо старое говно, либо не сильно лучше младших квенов/гемини 27B/31B, пусть даже и тоже недавно вышли.
И вот она та самая жопа из первого абзаца - нет средней руки железки и нет средней руки модельки. В итоге либо ты сидишь на 24/48гб и юзаешь условный квен 27б, либо ты въёбываешь пятизнак грина в систему, собирая кластерок из пары PRO 6000, либо ты собираешь бюджет из четырёх-шести-восьми B70 и и втыкаешь туда что-нибудь интересное о 200+ гигах
Всё остальное будет полумерами и постоянным примирением с чем-то имхо. Ну типа, тот же Spark при всей своей пиздатости крайне плохо работает с dense модельками >20B или просто с любыми, где надо жирный компьют, потому что как бы а что вы хотите от такой малышки в коробке из-под конфет. Тот же мистраль медиум там выдаёт ~7 токенов, если мне память не изменяет. Это смешно. Я думаю, ты и сам на клавиатуре с такой же скоростью можешь печатать. :D
Собственно, в подтверждение всего вышесказанного можно процедить тот же реддит и увидеть, что публика там так и делится:
1. Пацаны с 24-32Gb, которые юзают квены/гемини 27б/31б;
2. Те же пацаны, но с несколькими видяхами на 48-96гб, которые юзают либо то же самое на жирных квантах и бОльших контекстах, либо что-то типа старого кодер некста;
3. Пацаны на ламбо с несколькими RTX6000, H200 и прочие подобные ребята из гугла, которым пойти пощупать новый GLM 5.2 на полтора терабайта - как воды попить.
Как видим, пропасть между 1-2 и 3 не заполнена ничем. Отвечая на незаданный вопрос "какого хуя" мысль такая: потому что ровно здесь и кроется sweet spot, который потенциально может закопать весь коммерс по предоставлению облачных решений. Те, что поменьше, угрозы не представляют, а тех, что побольше - слишком мало, чтобы угрожать. Но дай ты людям за недорого то же Qwen3.6 27B, только умноженный на пять или десять, и в целом всё, досвидос, облачка можно закрывать, клиентов у вас не будет. Примерно точно так же в своё время рендер-фермы сдохли - видяхи стали достаточно жирными, чтобы ребята могли у себя дома вменяемо рендерить, а большинству студий достаточно 6-10 на ферме и всё это за копейки.
Из железа у тебя прям щас есть выбор из:
1. Малый компьют с дохера объёма (370/395/спарки/макбуки/мини/студио/нэйм ит);
2. Средний компьют с мало объёма (3090/4090/b60/b70/7900/9700/нэйм ит);
3. Толстый компьют с дохера объёма (PRO6000/A100/H100/H200/MI250/нэйм ит).
Что отсутствует? Всё верно - средний компьют с дохера объема. Условно говоря, что-то типа RTX4090 на 64гб за недорого. На рынке ровно ничего подобного нет. И вот это довольно интересный момент, потому что РОВНО ТАКАЯ железка всем и нужна в массовом секторе имхо. В какой-то степени я даже удивлён, что всё ещё никто ничего подобного не предлагает, потому что отрывали бы с руками кмк.
Докидываем сюда мультипликатор веселья в виде охуевших цен не разное и всё становится ещё интереснее.
Но допустим, что такая железка у нас есть. Вопрос теперь не менее интересный: а что в неё грузить?
Если говорить про квантованные модели, то у тебя есть:
1. Квен/гемини 27B/31B под 24-32Гб;
2. Целый ворох устаревших на 3-4 поколения моделей типа 70B/120b для 48-64гб;
3. Весь прочий жир типа 0.3T-1T++ моделей, для чего надо 250-300++ Гб.
Что отсутствует? Всё верно - что-то между 2 и 3. Тупо нет и пока не предвидится хороших, качественных моделек такого объёма. Условно говоря, у тебя до сих пор нет какого-нибудь "Qwen 3.6 Coder Next", который при своих 80B как раз влезал в 48 гиговые карточки. То есть, условная 120-ка должна без проблем влезать в 64гб. Но такой модельки сука нет, а всё остальное в подобном типоразмере - либо старое говно, либо не сильно лучше младших квенов/гемини 27B/31B, пусть даже и тоже недавно вышли.
И вот она та самая жопа из первого абзаца - нет средней руки железки и нет средней руки модельки. В итоге либо ты сидишь на 24/48гб и юзаешь условный квен 27б, либо ты въёбываешь пятизнак грина в систему, собирая кластерок из пары PRO 6000, либо ты собираешь бюджет из четырёх-шести-восьми B70 и и втыкаешь туда что-нибудь интересное о 200+ гигах
Всё остальное будет полумерами и постоянным примирением с чем-то имхо. Ну типа, тот же Spark при всей своей пиздатости крайне плохо работает с dense модельками >20B или просто с любыми, где надо жирный компьют, потому что как бы а что вы хотите от такой малышки в коробке из-под конфет. Тот же мистраль медиум там выдаёт ~7 токенов, если мне память не изменяет. Это смешно. Я думаю, ты и сам на клавиатуре с такой же скоростью можешь печатать. :D
Собственно, в подтверждение всего вышесказанного можно процедить тот же реддит и увидеть, что публика там так и делится:
1. Пацаны с 24-32Gb, которые юзают квены/гемини 27б/31б;
2. Те же пацаны, но с несколькими видяхами на 48-96гб, которые юзают либо то же самое на жирных квантах и бОльших контекстах, либо что-то типа старого кодер некста;
3. Пацаны на ламбо с несколькими RTX6000, H200 и прочие подобные ребята из гугла, которым пойти пощупать новый GLM 5.2 на полтора терабайта - как воды попить.
Как видим, пропасть между 1-2 и 3 не заполнена ничем. Отвечая на незаданный вопрос "какого хуя" мысль такая: потому что ровно здесь и кроется sweet spot, который потенциально может закопать весь коммерс по предоставлению облачных решений. Те, что поменьше, угрозы не представляют, а тех, что побольше - слишком мало, чтобы угрожать. Но дай ты людям за недорого то же Qwen3.6 27B, только умноженный на пять или десять, и в целом всё, досвидос, облачка можно закрывать, клиентов у вас не будет. Примерно точно так же в своё время рендер-фермы сдохли - видяхи стали достаточно жирными, чтобы ребята могли у себя дома вменяемо рендерить, а большинству студий достаточно 6-10 на ферме и всё это за копейки.
Forwarded from PSD | Дизайн-пространство
This media is not supported in your browser
VIEW IN TELEGRAM
Сайт by Robbin Cenijn #сайт
Forwarded from Daily Coding 🔥
🛠 Buefy - легкий фреймворк UI для Vue.js построен с использованием популярного элемента на основе CSS библиотека Бульма. В ней есть все составляющие типичного веб-приложения должен в том числе динамические элементы, как модели, тосты и уведомления, что позволяет разработчикам быстро добавлять элементы пользовательского интерфейса в своих проектах Vue.js .
🌍 Сайт
Daily Coding #инструменты #Vue & Max
🌍 Сайт
Daily Coding #инструменты #Vue & Max
Forwarded from Node.JS [ru] | Серверный JavaScript
Diagnostics Channel: Загляни внутрь Node.js в production без console.log и перезаливок
Когда приложение падает в production, а логи пусты - начинается классика: залипаешь в терминал с
Что за зверь?
Модуль
Где выстрелит?
- Утечки HTTP-соединений - канал
- HTTP/2 сессии и их жизненный цикл
- Работа DNS-резолвера
- Создание и завершение Worker Threads
- Зависания событийного цикла - канал
Пример: ловим утечки HTTP-соединений
Кладёшь этот код в
Как тащить в production?
- Условный require:
- Или динамически подключай по
- Только помни: подписка - синхронная операция. Не делай внутри тяжёлых вычислений или блокирующих I/O, иначе забьёшь event loop и ухудшишь производительность
Вывод:
Diagnostics Channel позволяет заглянуть внутрь Node.js в реальном времени под нагрузкой, чтобы поймать утечки и задержки до того, как они уронят production, причём без единой правки кода приложения.
Когда приложение падает в production, а логи пусты - начинается классика: залипаешь в терминал с
console.log, комментируешь половину кода и перезаливаешь. Но у Node.js есть встроенный механизм для подписки на внутренние события движка и модулей без правки исходников. Называется diagnostics_channel.Что за зверь?
Модуль
diagnostics_channel даёт каналы, именуемые по схеме модуль.событие.подсобытие. Через них V8, libuv и сам Node.js эмитят структурированные данные о внутренних операциях. Подписаться можно без правки кода приложения - просто инициализируешь слушателя в отдельном файле и подключаешь через флаг --require.Где выстрелит?
- Утечки HTTP-соединений - канал
http.client.request.create- HTTP/2 сессии и их жизненный цикл
- Работа DNS-резолвера
dns- Создание и завершение Worker Threads
- Зависания событийного цикла - канал
tickПример: ловим утечки HTTP-соединений
const diagnosticsChannel = require('diagnostics_channel');
const clientRequestChannel = diagnosticsChannel.channel('http.client.request.create');
clientRequestChannel.subscribe(({ request, socket }) => {
const startTime = Date.now();
request.on('response', (res) => {
console.log(Request to ${request.hostname} completed (${Date.now() - startTime}ms));
});
socket.on('close', () => {
if (Date.now() - startTime > 5000) {
console.warn(Long-lived socket detected: ${socket.remotePort});
}
});
});Кладёшь этот код в
diagnostics.js, запускаешь с флагом node --require ./diagnostics.js app.js - и никаких изменений в исходниках приложения.Как тащить в production?
- Условный require:
NODE_DEBUG_DIAGNOSTICS=1 node app.js с проверкой в коде- Или динамически подключай по
process.env при старте, чтобы не плодить лишние подписки- Только помни: подписка - синхронная операция. Не делай внутри тяжёлых вычислений или блокирующих I/O, иначе забьёшь event loop и ухудшишь производительность
Вывод:
Diagnostics Channel позволяет заглянуть внутрь Node.js в реальном времени под нагрузкой, чтобы поймать утечки и задержки до того, как они уронят production, причём без единой правки кода приложения.
Forwarded from PSD | Дизайн-пространство
Media is too big
VIEW IN TELEGRAM
Vector Archects - Corporate webse
https://.com/shots/22571057-Vector-Archects-Corporate-webse
https://.com/shots/22571057-Vector-Archects-Corporate-webse
Forwarded from ai.dot(ufna, dev)
А это вы видели? Загружаем модельку вам прямо в браузер!
https://huggingface.co/spaces/webml-community/gemma-4-webgpu-kernels
https://huggingface.co/spaces/webml-community/gemma-4-webgpu-kernels
Forwarded from Daily Coding 🔥
Погрузитесь в ИТ за 5 дней и получите доступ к высокооплачиваемым вакансиям!
Бесплатный короткий курс для тех, кто хочет не просто понять, чем занимаются айтишники, но и получить реальный опыт работы с ИТ‑системами.
Всего за 5 дней вы освоите ключевые компоненты ИТ‑сферы, разберёте 6 профессий и получите возможность выйти на зарплату 150–250 тыс.
Курс полностью практический. 8 мини‑проектов с реальными задачами, где вы научитесь: писать код, работать с инфраструктурой, разбираться в сетях, облаке и защите данных.
Подойдёт новичкам и тем, кто уже в ИТ. Количество мест ограничено — регистрируйтесь по ссылке и начинайте практику.
Реклама. Информация о рекламодателе по ссылкам в посте.
Бесплатный короткий курс для тех, кто хочет не просто понять, чем занимаются айтишники, но и получить реальный опыт работы с ИТ‑системами.
Всего за 5 дней вы освоите ключевые компоненты ИТ‑сферы, разберёте 6 профессий и получите возможность выйти на зарплату 150–250 тыс.
Курс полностью практический. 8 мини‑проектов с реальными задачами, где вы научитесь: писать код, работать с инфраструктурой, разбираться в сетях, облаке и защите данных.
Подойдёт новичкам и тем, кто уже в ИТ. Количество мест ограничено — регистрируйтесь по ссылке и начинайте практику.
Реклама. Информация о рекламодателе по ссылкам в посте.
Forwarded from Daily Coding 🔥
📖Collaborative Software Design
🖋Baas-Schwegler Kenny, Van Kelle Evelyn, Verschatse Gien 2025
В книге «Совместное проектирование программного обеспечения» вы познакомитесь с принципами, методами и инструментами, способствующими безопасному общению при выявлении бизнес-проблем, формализации требований и реализации программного проекта. В ней рассказывается о таких признанных инструментах совместного моделирования, как «штурм событий», «составление примеров», «составление карт Уордли» и «сторителлинг предметной области», а также о уникальных подходах к управлению когнитивными искажениями, конфликтами и организационной иерархией. Независимо от того, являетесь ли вы заинтересованной стороной в бизнесе, техническим специалистом или профессиональным координатором, вы научитесь слышать всех участников процесса и извлекать пользу из их вклада.
💾 Скачать книгу
Daily Coding #книги #архитектура & Max
🖋Baas-Schwegler Kenny, Van Kelle Evelyn, Verschatse Gien 2025
В книге «Совместное проектирование программного обеспечения» вы познакомитесь с принципами, методами и инструментами, способствующими безопасному общению при выявлении бизнес-проблем, формализации требований и реализации программного проекта. В ней рассказывается о таких признанных инструментах совместного моделирования, как «штурм событий», «составление примеров», «составление карт Уордли» и «сторителлинг предметной области», а также о уникальных подходах к управлению когнитивными искажениями, конфликтами и организационной иерархией. Независимо от того, являетесь ли вы заинтересованной стороной в бизнесе, техническим специалистом или профессиональным координатором, вы научитесь слышать всех участников процесса и извлекать пользу из их вклада.
💾 Скачать книгу
Daily Coding #книги #архитектура & Max
Forwarded from Node.JS [ru] | Серверный JavaScript
Event Loop Lag при тысячах setTimeout: как очередь таймеров убивает latency в production
Когда на сервере больше 1000 активных setTimeout или setInterval, latency неожиданно растет, I/O начинает тормозить, а пользователи жалуются на задержки. Многие разработчики считают, что таймеры безвредны, но на практике их перебор в одной фазе event loop блокирует весь tick.
Всё упирается в фазы цикла событий:
- timers — коллбеки от setTimeout и setInterval
- pending callbacks — I/O ошибки
- idle, prepare — внутренняя кухня libuv
- poll — новые I/O события
- check — очередь setImmediate
- close callbacks — закрытие соединений
Проблема: когда у вас 10 000 активных setTimeout, фаза timers отрабатывает десятки миллисекунд. Всё остальное стоит в очереди. I/O, новые запросы, ответы — всё ждёт, пока переберутся таймеры.
Реальный случай из практики
Был сервис с heartbeats для клиентов. Каждый клиент держал рекурсивный setTimeout:
Для 5000 клиентов каждый tick на фазе timers прогонял до 5000 коллбеков. Попутно лагали все остальные запросы — пользователи чувствовали задержки, мониторинг показывал event loop lag > 100ms.
Что с этим делать?
Во-первых, отлаживать. Берём профайлер Node.js:
Смотрим лог — находим, сколько времени уходит на фазу timers. Часто это открытие.
Во-вторых, оптимизировать.
- Ограничьте количество активных таймеров. Сгруппируйте несколько heartbeat-задач в один setInterval.
- Там, где возможна замена, используйте setImmediate. Он живёт на фазе check — не блокирует poll и timers.
- Мониторьте event loop lag через
Можно ещё раскидать тяжёлые таймерные задачи по worker_threads — чтобы они не тормозили главный поток.
Вывод:
Большое количество таймеров — тихий убийца производительности, который часто замечают слишком поздно, но своевременный профилинг и рефакторинг очередей могут снизить latency в разы.
Когда на сервере больше 1000 активных setTimeout или setInterval, latency неожиданно растет, I/O начинает тормозить, а пользователи жалуются на задержки. Многие разработчики считают, что таймеры безвредны, но на практике их перебор в одной фазе event loop блокирует весь tick.
Всё упирается в фазы цикла событий:
- timers — коллбеки от setTimeout и setInterval
- pending callbacks — I/O ошибки
- idle, prepare — внутренняя кухня libuv
- poll — новые I/O события
- check — очередь setImmediate
- close callbacks — закрытие соединений
Проблема: когда у вас 10 000 активных setTimeout, фаза timers отрабатывает десятки миллисекунд. Всё остальное стоит в очереди. I/O, новые запросы, ответы — всё ждёт, пока переберутся таймеры.
Реальный случай из практики
Был сервис с heartbeats для клиентов. Каждый клиент держал рекурсивный setTimeout:
function heartBeat(clientId) {
setTimeout(() => {
// Тяжёлая операция с БД + проверка состояния
heartBeat(clientId);
}, 1000);
}Для 5000 клиентов каждый tick на фазе timers прогонял до 5000 коллбеков. Попутно лагали все остальные запросы — пользователи чувствовали задержки, мониторинг показывал event loop lag > 100ms.
Что с этим делать?
Во-первых, отлаживать. Берём профайлер Node.js:
node --prof app.js
Смотрим лог — находим, сколько времени уходит на фазу timers. Часто это открытие.
Во-вторых, оптимизировать.
- Ограничьте количество активных таймеров. Сгруппируйте несколько heartbeat-задач в один setInterval.
- Там, где возможна замена, используйте setImmediate. Он живёт на фазе check — не блокирует poll и timers.
- Мониторьте event loop lag через
process.hrtime или модуль event-loop-stats. Если lag > 50ms — это звоночек.Можно ещё раскидать тяжёлые таймерные задачи по worker_threads — чтобы они не тормозили главный поток.
Вывод:
Большое количество таймеров — тихий убийца производительности, который часто замечают слишком поздно, но своевременный профилинг и рефакторинг очередей могут снизить latency в разы.