DevNotes Live
6 subscribers
84.3K photos
12K videos
195 files
35.4K links
Автоматический агрегатор IT ресурсов в Telegram (@devnotes_robot)
Информация: https://t.me/devnotes_live/121
Download Telegram
Как temporal.io SDK ломает V8 heap snapshot в длительных Workflow

Если ваш Workflow Execution живёт неделями, готовьтесь к сюрпризам: V8 перестаёт адекватно собирать мусор, а heap snapshot превращается в помойку из ретейнеров. Частая ошибка — считать, что GC справится сам, но Temporal SDK активно мешает ему.

Почему GC не работает
SDK держит один V8 isolate на весь Worker. Пока Workflow крутится, Temporal сохраняет историю состояний и коллбэки. V8 честно чистит память, но SDK не даёт объектам уйти через замыкания в таймерах и маппингах. WeakRef и FinalizationRegistry в детерминированном коде — отдельная боль: GC просто не видит, что объекты уже никому не нужны. В результате в heap зависают ретейнеры вроде WorkflowContext и ActivityContext.

Production-кейс: Map на миллион элементов
Пишете долгий воркфлоу с Map на миллион элементов, потом ставите Workflow.sleep('1 year'). Этот Map останется в памяти до перезапуска воркера. Почему: SDK замораживает каждое состояние через Object.freeze(), и ссылки на объекты в V8 heap остаются. V8 считает их живыми, пока isolate жив — heap аккумулируется, RSS ползёт вверх, GC тормозит.

Практические советы
* Обновляйтесь до @temporalio/workflow >=1.8.0 — там появился явный context.reset().
* Чистите Map и Set руками: largeMap.clear().
* Дёргайте maxWorkflowCachedExecution, чтобы принудительно пересоздавать isolate.
* Мониторьте heap через process.memoryUsage() и рестартуйте Worker, если память перевалила за лимит.

Вывод: В длительных Workflow явное управление памятью важнее надежды на GC — закладывайте очистку структур данных и рестарты Worker в архитектуру с самого начала.
На Stepik запустили мощный курс по «Troubleshooting Docker и Kubernetes: поиск и устранение проблем»

В программе только важные аспекты:

— troubleshooting Docker и образов
— диагностика сетевых проблем
— настройка readiness/liveness probes
— отладка pod’ов, деплоев и ingress
— анализ логов контейнеров и кластера
— разбор ошибок CrashLoopBackOff, OOMKilled, ImagePullBackOff и других

Собеседования на DevOps/SRE сейчас всё чаще строятся вокруг реальных инцидентов. Данный курс фокусируется именно на таких сценариях и помогает в подготовке к практическим вопросам

48 часов доступен со скидкой 25%

↗️ Пройти курс на Stepik
Please open Telegram to view this post
VIEW IN TELEGRAM
«100 главных принципов дизайна»
Сьюзан Уэйшенк
Forwarded from Daily Coding 🔥
📖Video Game Design For Dummies
🖋Mandeville Alexia 2025

Книга «Разработка видеоигр для чайников» расскажет вам, что нужно для создания игр — от разработки концепции до завершения проекта. Вы изучите теорию, лежащую в основе создания увлекательных игр, и познакомитесь с инструментами, которые помогут воплотить ваши игровые идеи в жизнь. Опытный разработчик видеоигр научит вас основам игрового дизайна, а также тому, как мотивировать игроков и вовлекать их в процесс. Выбирайте подходящие игровые движки и инструменты для разработки любого проекта и получайте пошаговые рекомендации по тестированию и отладке созданных вами игр.

💾 Скачать книгу

Daily Coding #книги #gamedev & Max
False Sharing в SharedArrayBuffer на NUMA: скрытый убийца производительности Node.js
Параллельная обработка данных через worker_threads с SharedArrayBuffer часто даёт неожиданное падение производительности вместо ожидаемого ускорения. Причина — false sharing, который на NUMA-системах с несколькими сокетами может снижать пропускную способность в десятки раз, оставаясь незамеченным в обычных профилировщиках.

Суть проблемы
Когда два воркера пишут в разные элементы одного Int32Array, но они попадают в одну кэш-линию (64 байта = 16 int32), процессор инвалидирует кэш у соседнего ядра. Протокол MESI создаёт лавину обменов между L1-кэшами, а на NUMA это усугубляется межсокетными задержками.
// Проблемный код: data[0] и data[1] в одной кэш-линии
const sharedBuffer = new SharedArrayBuffer(4 * 1024);
const data = new Int32Array(sharedBuffer);
// Worker 1: data[0]++ | Worker 2: data[1]++


Диагностика через аппаратные счётчики
Используйте perf для выявления:
perf stat -e cache-misses,cache-references,LLC-load-misses node app.js

Резкий рост LLC misses при добавлении воркеров — явный признак. На NUMA добавьте проверку uncore_imc событий для обнаружения межсокетных обращений.

Устранение: padding и привязка к NUMA
Разделите данные на границы кэш-линии — отступ в 16 элементов для Int32Array:
const CACHE_LINE = 16;
const realIndex = workerId * CACHE_LINE;

Это устраняет конфликт, но не решает проблему доступа к памяти другого сокета. Привяжите воркеров к локальным нодам через numactl или модуль numa-bindings:
// Привязка к NUMA-ноде 0
worker.setEnvironment({ 'NODE_NUMA_NODE': '0' });


Типичная ошибка
Многие разработчики используют Atomics.store/load каждую итерацию, пытаясь синхронизировать данные. Это лишь добавляет барьеры памяти и усугубляет false sharing. Используйте редкую синхронизацию (раз в N итераций) или локальные буферы с периодическим слиянием.

Production-совет
На высоких нагрузках (8+ ядер) комбинация padding + привязка к локальной памяти даёт прирост 5-10 раз. Для 4-сокетных систем используйте распределение SharedArrayBuffer через libnuma: массив делится на сегменты по числу нод, каждый воркер пишет только в свой сегмент.

Вывод: False sharing на NUMA требует обязательного выравнивания по кэш-линии и привязки worker_threads к локальным нодам памяти — только так можно получить реальный прирост от параллельной обработки.
Forwarded from ai.dot(ufna, dev)
Media is too big
VIEW IN TELEGRAM
Один из сайтов Spotify, созданный для сближения и объединения людей. Живой пример инклюзивности в дизайне. Небольшой сайт с 3D объектами и вложенными в них историями и видео от разных пользователей, учатников и создателей Spotify.

Сайт тут
Replay: Reprogramming biology
Rollin - Bakery Shop Website

#веб
Forwarded from Daily Coding 🔥
🛠 sabiql - быстрый TUI без драйверов для просмотра, запроса и редактирования баз данных PostgreSQL

🌍 Сайт

Daily Coding #инструменты #SQL & Max
Forwarded from Dezzigners
🧰 Food Icons — 100+ наиболее используемых иконок еды, минималистичный стиль

Dezzigners
Starvation в worker_threads: почему libuv заставляет ваши воркеры голодать при смешанной нагрузке I/O и CPU

Когда вы смешиваете I/O и CPU-bound задачи в worker_threads, неочевидная деталь может убить производительность. В production часто встречается ситуация: воркеры простаивают, хотя ядра свободны. Корень проблемы - приоритеты очередей libuv.

Как libuv ест процессорное время воркеров
У libuv есть I/O callback queue с высоким приоритетом. Если в главном потоке активны I/O операции (чтение файлов, сетевые запросы), они обрабатываются первыми. Worker_threads получают CPU только на этапе idle. В результате воркер может ждать 100-200 мс при реальной нагрузке, даже если на ядрах нет другой работы.

Диагностика: ловим задержки
Начните с event loop lag. Вот production-ready пример:
const { performance } = require('perf_hooks');
const start = performance.now();
setTimeout(() => {
const lag = performance.now() - start - 100;
if (lag > 50) console.warn(Event loop lag: ${lag.toFixed(2)}ms);
// Если lag растет - воркеры голодают
}, 100);

Также полезно смотреть process._getActiveHandles() - там видно, какие задачи висят в libuv. Типичная ошибка: думать, что раз воркер в отдельном потоке, он не зависит от I/O в главном.

Четыре способа исправить
1. Ограничьте частоту I/O в главном потоке. Не спамьте readFile каждые 10 мс - используйте debounce или batch.
2. Разбивайте данные на чанки с setImmediate(). Это перераспределяет приоритет очереди libuv и дает воркерам больше шансов:
function processChunks(data) {
const chunk = data.splice(0, 100);
if (chunk.length) {
setImmediate(() => processChunks(data));
}
}

3. Настройте UV_THREADPOOL_SIZE. Не ставьте максимальное значение - обычно достаточно os.cpus().length * 2, но не больше 4.
4. Выделите одно ядро главному потоку: workerCount = os.cpus().length - 1.

Важный предостережение
Даже с настройками worker_threads остается зависимым от главного event loop. Если не изолировать CPU-bound и I/O задачи в разные процессы, при пиковой нагрузке воркеры все равно будут ждать. Планирование завязано на libuv - не игнорируйте это.

Вывод: Причина starvation не в worker_threads, а в неявных приоритетах libuv - решайте её через контроль I/O в главном потоке и разбивку задач с setImmediate.
Фейк-вакансии: почему в ответ тишина? 🤐

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

Читать на дизайнерс | #статья
Резюме

А у меня же много лидов дизайна и директоров по исследованиям? Есть резюме специалиста по доступности

"я ищу работу в сфере цифровой доступности, вот резюме — https://career.habr.com/kamunicorn"

Работала в РТЛабс (разработчик портала Госуслуги), до этого написала курс по веб-доступности для HTML Academy
Странные паттерны
Капиллярная чашка НАСА — это чашка для условий невесомости, разработанная астронавтом НАСА Дональдом Петтитом на Международной космической станции. Это открытая питьевая чашка, предназначенная для использования в условиях микрогравитации. Она появилась благодаря желанию Петтита пить воду в космосе без пакета и трубочки.
Основная идея в том, что для того, чтобы отказаться от трубочки, нужно создать внутренний угол чашки, который создает мощное поверхностное натяжение жидкости. Напиток естественным образом притягивается к острому краю и удерживается там, не разлетаясь по космическому кораблю.

https://www.rit.edu/vignellicenter/product-timecapsule/nasa-capillary-cup

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