Forwarded from Node.JS [ru] | Серверный JavaScript
WeakRef и циклы: тихая утечка памяти в долгоживущих процессах
WeakRef в Node.js — инструмент для умных кэшей и подписок, но в долгоживущих серверных процессах он может стать причиной неочевидной утечки памяти. Самая распространенная ошибка — циклическая структура, где WeakRef замыкается с сильными ссылками, и GC молча перестает собирать объекты.
Как возникает утечка
В серверных приложениях часто используется дерево компонентов. Если дочерний элемент хранит WeakRef на родителя, а родитель — сильную ссылку на дочерний, цикл замкнут. GC видит, что объект родителя доступен через WeakRef, но сам WeakRef жив, и сборка блокируется. Результат — плавный рост heap, незаметный неделями.
Диагностика в production
- Снимайте heap snapshots через
- Включайте
- Мониторинг
Практические решения
Самый надежный способ — разорвать цикл. Используйте
Ошибка, которую все допускают
WeakRef внутри замыкания на
Вывод: WeakRef — не панацея: в долгоживущих процессах всегда проверяйте цепочки замыканий и снимайте heap snapshots, иначе тихая утечка памяти станет причиной падения сервера.
WeakRef в Node.js — инструмент для умных кэшей и подписок, но в долгоживущих серверных процессах он может стать причиной неочевидной утечки памяти. Самая распространенная ошибка — циклическая структура, где WeakRef замыкается с сильными ссылками, и GC молча перестает собирать объекты.
Как возникает утечка
В серверных приложениях часто используется дерево компонентов. Если дочерний элемент хранит WeakRef на родителя, а родитель — сильную ссылку на дочерний, цикл замкнут. GC видит, что объект родителя доступен через WeakRef, но сам WeakRef жив, и сборка блокируется. Результат — плавный рост heap, незаметный неделями.
Диагностика в production
- Снимайте heap snapshots через
heapdump или Chrome DevTools. Ищите раздел System / WeakRef — там лежат недоступные объекты.- Включайте
--trace-gc и --trace-gc-verbose. Они покажут, какие объекты GC не может собрать из-за слабых ссылок.- Мониторинг
process.memoryUsage() и v8.getHeapStatistics() — кривая роста без видимых причин говорит о проблеме.Практические решения
Самый надежный способ — разорвать цикл. Используйте
FinalizationRegistry для явного освобождения ресурсов:const registry = new FinalizationRegistry((held) => {
console.log('cleaned', held);
});
class Child {
constructor(parent) {
this.parentWeakRef = new WeakRef(parent);
registry.register(this, 'child');
}
getParent() {
return this.parentWeakRef.deref();
}
}Ошибка, которую все допускают
WeakRef внутри замыкания на
this — классика. Например, в WebSocket подписках: () => this.parent.someMethod сохраняет контекст с сильной ссылкой на весь граф. Всегда пишите явную проверку: this.parentWeakRef?.deref()?.someMethod. Иначе цикл восстановится.Вывод: WeakRef — не панацея: в долгоживущих процессах всегда проверяйте цепочки замыканий и снимайте heap snapshots, иначе тихая утечка памяти станет причиной падения сервера.
Forwarded from Node.JS [ru] | Серверный JavaScript
Диагностика и устранение indefinite suspension при мониторинге HTTP-запросов через async-hooks
Ситуация знакомая: используешь async-hooks для отслеживания длинных HTTP-запросов, и вдруг приложение начинает подвисать. Чаще всего это indefinite suspension из-за unhandled rejection.
В чём соль. async-hooks создаёт контекст для каждой асинхронной операции. Если внутри этого контекста Promise упал (rejection), а обработчика нет, хук может зависнуть в ожидании. Сборщик мусора не срабатывает, ресурсы текут — и приложение виснет.
Как ловить
Первое — глобальный перехват unhandledRejection:
Второе — запускай с флагом
Что делать
Вариант 1. Просто и надёжно — добавить
Вариант 2. Явное управление контекстами через destroy. Заводишь Map, чистишь её при завершении:
Вариант 3. Принудительный таймаут. Запускаешь интервал, проверяешь застрявшие контексты (скажем, те, что висят дольше 30 секунд) и прибиваешь их.
На заметку. Если Node.js 14+, бери
Вывод: Indefinite suspension лечится связкой глобального обработчика ошибок и чёткого контроля жизненного цикла контекстов.
Ситуация знакомая: используешь async-hooks для отслеживания длинных HTTP-запросов, и вдруг приложение начинает подвисать. Чаще всего это indefinite suspension из-за unhandled rejection.
В чём соль. async-hooks создаёт контекст для каждой асинхронной операции. Если внутри этого контекста Promise упал (rejection), а обработчика нет, хук может зависнуть в ожидании. Сборщик мусора не срабатывает, ресурсы текут — и приложение виснет.
Как ловить
Первое — глобальный перехват unhandledRejection:
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});Второе — запускай с флагом
--trace-warnings, чтобы видеть стек.Что делать
Вариант 1. Просто и надёжно — добавить
.catch() в каждый Promise внутри хука:const hook = createHook({
init(asyncId, type) {
if (type === 'HTTPINCOMINGMESSAGE') {
const requestPromise = someAsyncOperation();
requestPromise.catch(err => console.error(Request ${asyncId} failed:, err));
}
}
});
hook.enable();Вариант 2. Явное управление контекстами через destroy. Заводишь Map, чистишь её при завершении:
const contexts = new Map();
hook.init(asyncId, type) {
if (type === 'HTTPINCOMINGMESSAGE') {
contexts.set(asyncId, Date.now());
}
}
hook.destroy(asyncId) {
contexts.delete(asyncId);
}
Вариант 3. Принудительный таймаут. Запускаешь интервал, проверяешь застрявшие контексты (скажем, те, что висят дольше 30 секунд) и прибиваешь их.
На заметку. Если Node.js 14+, бери
AsyncLocalStorage — он сам управляет контекстом. И никогда не создавай Promise внутри init без .catch(). Тестируй с --async-stack-traces.Вывод: Indefinite suspension лечится связкой глобального обработчика ошибок и чёткого контроля жизненного цикла контекстов.
Forwarded from Node.JS [ru] | Серверный JavaScript
Код я написал за две недели. Продавать его боюсь до сих пор
Три недели назад расширение прошло ревью и появилось в Chrome Web Store. С тех пор ни анонса, ни поста, ни сообщения людям, которые его ждали. Тишина. Это уже не первый раз: в мае автор точно так же на месяц пропал в код, лишь бы не заниматься продвижением. В статье разбирается, почему разработчик прячется от собственного продукта, и приводятся замеры, что происходит с цифрами, когда прятаться перестаёшь.
Читать далее →
Три недели назад расширение прошло ревью и появилось в Chrome Web Store. С тех пор ни анонса, ни поста, ни сообщения людям, которые его ждали. Тишина. Это уже не первый раз: в мае автор точно так же на месяц пропал в код, лишь бы не заниматься продвижением. В статье разбирается, почему разработчик прячется от собственного продукта, и приводятся замеры, что происходит с цифрами, когда прятаться перестаёшь.
Читать далее →
Forwarded from PSD | Дизайн-пространство
Качай насмотренность правильно
Дизайн-редактор: Узнай, почему простое "насмотренность" не всегда помогает в развитии дизайнера
Читать на дизайнерс | #статья
Дизайн-редактор: Узнай, почему простое "насмотренность" не всегда помогает в развитии дизайнера
Читать на дизайнерс | #статья
Forwarded from PSD | Дизайн-пространство
За пятисекундной ИИ-обложкой — часы мыслительной работы
Изучите процесс создания анимационных обложек для журнала "Юновью" от графического дизайнера и ИИ-креатора Сони. Как идея превращается в уникальную анимацию?
Читать на дизайнерс | #статья
Изучите процесс создания анимационных обложек для журнала "Юновью" от графического дизайнера и ИИ-креатора Сони. Как идея превращается в уникальную анимацию?
Читать на дизайнерс | #статья
Forwarded from PSD | Дизайн-пространство
БАЗА ЗНАНИЙ ДИЗАЙНЕРА
Илья Сидоренко (продуктовый дизайнер с опытом 13+ лет и автор бестселлера «Дизайнер интерфейсов») создал бесплатную базу знаний для дизайнера.
Что в базе:
+ как дизайнеру выйти на 300к в месяц
+ бесплатный экспресс-курс по продуктовому дизайну
+ как найти работу в продукте (пошаговая стратегия)
+ экспресс-курс по UX-исследованиям
+ советы по оформлению портфолио и резюме
+ обновления каждый месяц
База знаний доступна в закрепленом сообщении канала Ильи «Дизайнер будущего».
Подписывайтесь на канал, изучайте Базу и применяйте. А если останутся вопросы – пишите лично Илье, он всегда готов поделиться опытом или советом.
Реклама. ИП Сидоренко И. А., ИНН: 503013064674, erid: CQH36pWzJqDgEKpZrdAfGM3ypirMnb9jwD4rzobqR3nN1f
Илья Сидоренко (продуктовый дизайнер с опытом 13+ лет и автор бестселлера «Дизайнер интерфейсов») создал бесплатную базу знаний для дизайнера.
Что в базе:
+ как дизайнеру выйти на 300к в месяц
+ бесплатный экспресс-курс по продуктовому дизайну
+ как найти работу в продукте (пошаговая стратегия)
+ экспресс-курс по UX-исследованиям
+ советы по оформлению портфолио и резюме
+ обновления каждый месяц
База знаний доступна в закрепленом сообщении канала Ильи «Дизайнер будущего».
Подписывайтесь на канал, изучайте Базу и применяйте. А если останутся вопросы – пишите лично Илье, он всегда готов поделиться опытом или советом.
Реклама. ИП Сидоренко И. А., ИНН: 503013064674, erid: CQH36pWzJqDgEKpZrdAfGM3ypirMnb9jwD4rzobqR3nN1f
Forwarded from PSD | Дизайн-пространство
Оркестратор промптов: как собрать связку из Sonnet, GPT и Nano Banana
Открытие необычного метода повышения продуктивности — как один простой шаг изменил мою жизнь и помог достичь новых высот
Читать на дизайнерс | #статья
Открытие необычного метода повышения продуктивности — как один простой шаг изменил мою жизнь и помог достичь новых высот
Читать на дизайнерс | #статья
Forwarded from PSD | Дизайн-пространство
6 вопросов про менторинг
Полезная статья в формате FAQ, где отвечают на самые частые вопросы о менторинге: чем он отличается от курсов, что входит в работу с ментором, можно ли его менять и как правильно выбрать. Отличный материал для тех, кто рассматривает менторинг как следующий шаг в развитии.
Читать на дизайнерс | #Карьера
Полезная статья в формате FAQ, где отвечают на самые частые вопросы о менторинге: чем он отличается от курсов, что входит в работу с ментором, можно ли его менять и как правильно выбрать. Отличный материал для тех, кто рассматривает менторинг как следующий шаг в развитии.
Читать на дизайнерс | #Карьера
Forwarded from Дизайн-Телега 🔥
Как мы создавали джингл «Додо Пиццы»
Откройте мир звукового брендинга: как звуки могут создавать эмоциональную связь с продуктом
Читать на дизайнерс | #статья
Откройте мир звукового брендинга: как звуки могут создавать эмоциональную связь с продуктом
Читать на дизайнерс | #статья
Forwarded from UI_UX inspiration
Мобильное приложение для фрилансеров
Категория: #приложение
Язык: #en
https://.com/shots/27243753-Freelance-Project-Briefs
Чат UI/UX
Категория: #приложение
Язык: #en
https://.com/shots/27243753-Freelance-Project-Briefs
Чат UI/UX
Forwarded from UI_UX inspiration
Forwarded from Daily Coding 🔥
🛠 PHP VCR —записывайте HTTP-взаимодействия вашего набора тестов и воспроизводите их при последующих запусках для быстрого, детерминированного и точного тестирования.
🌍 Сайт
Daily Coding #инструменты #PHP & Max
🌍 Сайт
Daily Coding #инструменты #PHP & Max
Forwarded from Node.JS [ru] | Серверный JavaScript
Диагностика и устранение гонок данных при конкурентном доступе к
В production сценариях с worker_threads и in-memory SQLite в WAL режиме разработчики часто забывают синхронизировать доступ. Итог —
Проблема: гонка без синхронизации
Несколько воркеров читают и пишут в одну in-memory базу без внешней координации. WAL помогает с параллельным чтением, но не спасает от гонок записи. Типичные проявления: ошибки
Решение: один писатель с явными блокировками
Выделите один воркер для критических записей (например, инкременты). Координируйте через
Production-oriented пример с
Начиная с Node.js 23 используйте
Предупреждение: in-memory WAL не для продакшена
In-memory база теряет данные при краше. Для реальных проектов используйте файловую базу с WAL — это гарантирует персистентность.
Вывод: гонки данных в SQLite лечатся одним писателем и явными блокировками через
node:sqlite из worker_threads через in-memory WAL-режимВ production сценариях с worker_threads и in-memory SQLite в WAL режиме разработчики часто забывают синхронизировать доступ. Итог —
SQLITE_BUSY, рассинхрон данных и дубли в уникальных полях.Проблема: гонка без синхронизации
Несколько воркеров читают и пишут в одну in-memory базу без внешней координации. WAL помогает с параллельным чтением, но не спасает от гонок записи. Типичные проявления: ошибки
SQLITE_BUSY, частичные обновления и потеря данных.Решение: один писатель с явными блокировками
Выделите один воркер для критических записей (например, инкременты). Координируйте через
SharedArrayBuffer и Atomics — это дешевле мьютексов. Воркеры-читатели используют отдельные соединения в WAL.Production-oriented пример с
BEGIN IMMEDIATEНачиная с Node.js 23 используйте
DatabaseSync. Обязательно PRAGMA journal_mode=WAL; и PRAGMA synchronous=NORMAL;:import { DatabaseSync } from 'node:sqlite';
const db = new DatabaseSync(':memory:', { readwrite: true, create: true });
db.exec('PRAGMA journal_mode=WAL;');
db.exec('PRAGMA synchronous=NORMAL;');
function safeUpdate(sql) {
db.exec('BEGIN IMMEDIATE;');
try {
db.exec(sql);
db.exec('COMMIT;');
} catch {
db.exec('ROLLBACK;');
throw new Error('Write failed');
}
}BEGIN IMMEDIATE блокирует запись сразу, избегая гонок. Без него два воркера могут начать транзакции одновременно — ловите SQLITE_BUSY.Предупреждение: in-memory WAL не для продакшена
In-memory база теряет данные при краше. Для реальных проектов используйте файловую базу с WAL — это гарантирует персистентность.
Вывод: гонки данных в SQLite лечатся одним писателем и явными блокировками через
BEGIN IMMEDIATE, давая скорость WAL без потери консистентности.Forwarded from UI_UX inspiration
Прототип дизайна для химчистки
Категория: #приложение
Язык: #en
https://.com/shots/16226238-Washted-Laundry-app-exploration
Категория: #приложение
Язык: #en
https://.com/shots/16226238-Washted-Laundry-app-exploration
Forwarded from UI_UX inspiration
Мобильное приложение персонального планировщика
Категория: #приложение
Язык: #en
https://.com/shots/25109333-Personal-Planner-Mobile-App-Concept
Чат UI/UX
Категория: #приложение
Язык: #en
https://.com/shots/25109333-Personal-Planner-Mobile-App-Concept
Чат UI/UX
Forwarded from Дизайн-Телега 🔥
Китайский чай: как выглядит индустрия, где кофе не главный
Стремление замечать необычное в повседневном и любовь к изучению упаковки в разных странах привели меня к созданию проекта "Дизайн-коммуналка" вместе с Дашей и Катей. Опыт, новые идеи и визуальные решения — вот что вдохновляет меня
Читать на дизайнерс | #статья
Стремление замечать необычное в повседневном и любовь к изучению упаковки в разных странах привели меня к созданию проекта "Дизайн-коммуналка" вместе с Дашей и Катей. Опыт, новые идеи и визуальные решения — вот что вдохновляет меня
Читать на дизайнерс | #статья
Forwarded from PSD | Дизайн-пространство
Китайский чай: как выглядит индустрия, где кофе не главный
Стремление замечать необычное в повседневном и любовь к изучению упаковки в разных странах привели меня к созданию проекта "Дизайн-коммуналка" вместе с Дашей и Катей. Опыт, новые идеи и визуальные решения — вот что вдохновляет меня
Читать на дизайнерс | #статья
Стремление замечать необычное в повседневном и любовь к изучению упаковки в разных странах привели меня к созданию проекта "Дизайн-коммуналка" вместе с Дашей и Катей. Опыт, новые идеи и визуальные решения — вот что вдохновляет меня
Читать на дизайнерс | #статья
Forwarded from Daily Coding 🔥
🛠 Wagtail — это система управления контентом с открытым исходным кодом, созданная на основе Django, с активным сообществом и коммерческой поддержкой. Она ориентирована на удобство использования и предоставляет широкие возможности для дизайнеров и разработчиков.
🌍 Сайт
Daily Coding #инструменты #Python & Max
🌍 Сайт
Daily Coding #инструменты #Python & Max