Forwarded from Daily Coding 🔥
🛠 BaguetteBox - это библиотека на основе JavaScript для создания адаптивных галерей лайтбоксов. Она очень легкая, доступна для мобильных устройств, проста в использовании и настройке и использует CSS3-переходы для плавных переходов изображений.
🌍 Сайт
Daily Coding #инструменты #JavaScript & Max
🌍 Сайт
Daily Coding #инструменты #JavaScript & Max
Forwarded from Node.JS [ru] | Серверный JavaScript
Скрытые убийцы Event Loop: ICU и Regex в Unicode-строках
Многие знают, что JSON.parse или fs.readFileSync блокируют Event Loop. Но есть враги похитрее - синхронные вызовы ICU и регулярных выражений на unicode-строках. Типичная ошибка: разработчики не подозревают, что методы нормализации или unicode-регулярки могут висеть десятки миллисекунд, оставаясь незамеченными до production-нагрузки.
Где прячется ICU
ICU тихо сидит в методах:
*
*
*
Регулярки с флагами
Пример скрытой блокировки
Как профилировать
* Используй
* Разбрасывай логи с
* Clinic.js:
Как устранять
Для ICU:
* Выноси нормализацию в Worker Threads
* Режь на чанки по 1000 символов, обрабатывай порциями
* Предобрабатывай данные на этапе загрузки, а не в рантайме
Для RegExp:
* Типичная ошибка: паттерны с backtracking, например
* Попробуй
* Разбивай строку через
Практический совет
Используй
Вывод: ICU и unicode-регекспы выглядят безобидно, но регулярно просаживают производительность - профилируйте их отдельно под нагрузкой, а не только в изолированных тестах.
Многие знают, что JSON.parse или fs.readFileSync блокируют Event Loop. Но есть враги похитрее - синхронные вызовы ICU и регулярных выражений на unicode-строках. Типичная ошибка: разработчики не подозревают, что методы нормализации или unicode-регулярки могут висеть десятки миллисекунд, оставаясь незамеченными до production-нагрузки.
Где прячется ICU
ICU тихо сидит в методах:
*
String.prototype.normalize()*
String.prototype.toLocaleLowerCase()*
Intl APIРегулярки с флагами
/u или /s на больших строках (эмодзи, иероглифы) могут висеть синхронно десятки миллисекунд. И ты даже не сразу поймешь, почему твой сервер тупит.Пример скрытой блокировки
const hugeText = '🦄'.repeat(100000);
const start = performance.now();
hugeText.normalize('NFC'); // ICU молча обрабатывает 100к символов
console.log(Блокировка: ${performance.now() - start}ms);
Как профилировать
* Используй
--prof флаг Node.js, потом node --prof-process.* Разбрасывай логи с
performance.now() до и после подозрительных операций.* Clinic.js:
npx clinic doctor -- node app.jsКак устранять
Для ICU:
* Выноси нормализацию в Worker Threads
* Режь на чанки по 1000 символов, обрабатывай порциями
* Предобрабатывай данные на этапе загрузки, а не в рантайме
const { Worker } = require('worker_threads');
const worker = new Worker('./normalize-worker.js');
worker.postMessage(hugeText);Для RegExp:
* Типичная ошибка: паттерны с backtracking, например
(a+)+b. Меняй на a+b.* Попробуй
re2 - без backtracking, работает предсказуемо* Разбивай строку через
string.slice, если можноconst safePattern = /^[a-z]+$/u;
Практический совет
Используй
monitorEventLoopDelay() из perf_hooks - он показывает задержки Event Loop в наносекундах. Запусти его в фоне и сравнивай с пиками нагрузки.Вывод: ICU и unicode-регекспы выглядят безобидно, но регулярно просаживают производительность - профилируйте их отдельно под нагрузкой, а не только в изолированных тестах.
Forwarded from PSD | Дизайн-пространство
This media is not supported in your browser
VIEW IN TELEGRAM
Коллекция анимированных сайтов для вдохновения.😍 🐈⬛
www.landing.love
А также галерея мобильных приложений с анимированным интерфейсом📲
appmotion.design
www.landing.love
А также галерея мобильных приложений с анимированным интерфейсом
appmotion.design
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from PSD | Дизайн-пространство
Forwarded from Designdealer
This media is not supported in your browser
VIEW IN TELEGRAM
Если не хватает свежей насмотренности, загляните в Recent.
Каждый день сервис публикует новую подборку лучшего дизайна со всего интернета.
recent.design
Каждый день сервис публикует новую подборку лучшего дизайна со всего интернета.
recent.design
Forwarded from PSD | Дизайн-пространство
This media is not supported in your browser
VIEW IN TELEGRAM
Сайт-портфолио дизайнера Felipe Elioenay выделяется среди других за счет яркой цветовой палитры и пролистывания экранов, как карточек. По структуре все достаточно просто. Нет кнопки "вверх", но есть большой ярковыраженный переход на главную, так что не потеряешься. В целом все контрастно, ярко и по делу.
Сайт тут
Сайт тут
Forwarded from Daily Coding 🔥
🛠 История активных сессий для Postgres — облегченная выборка событий ожидания без раздувания.
🌍 Сайт
Daily Coding #инструменты #SQL & Max
🌍 Сайт
Daily Coding #инструменты #SQL & Max
Forwarded from Node.JS [ru] | Серверный JavaScript
Неявный pinning в V8: как скрытые ссылки в прототипах и замыканиях мешают GC собирать мусор в production
Замечали, как Node.js внезапно начинает жрать память, хотя все объекты вроде уже не нужны? Чаще всего проблема в неявном pinning — GC просто не видит, что объекты можно собирать, из-за скрытых ссылок, живых прототипов и замыканий, которые V8 ошибочно считает нужными.
Прототипы и скрытые классы
У каждого объекта в V8 есть скрытый класс (HiddenClass) и ссылка на прототип. Пока жив экземпляр, весь прототип со всеми методами и данными остаётся в памяти. Это особенно критично для утечек через кеши:
Замыкания и живые контексты
V8 оптимизирует замыкания, но ошибается: если внутри замыкания объявлена большая переменная, а используется только часть контекста, GC всё равно держит всю аллокацию:
Неявные ссылки через WeakMap и Symbol.species
Слабая карта не гарантирует сборку — если ключ жив, значение тоже живёт. Symbol.species в подклассах может создать неявную ссылку на конструктор, удерживая целый прототип. Типичная ошибка — использовать Map для кеша, когда нужно WeakMap.
Что делать в production:
* Для кеширования используй WeakMap, а не Map — это единственный безопасный способ.
* В замыканиях явно зануляй большие объекты:
* Снимай heap snapshots через
* После создания массива экземпляров можно занулить
Вывод:
Одна невидимая ссылка через прототип или замыкание может закрепить сотни мегабайт в куче — используй WeakMap, явное зануление и профилирование, чтобы production не упал по памяти.
Замечали, как Node.js внезапно начинает жрать память, хотя все объекты вроде уже не нужны? Чаще всего проблема в неявном pinning — GC просто не видит, что объекты можно собирать, из-за скрытых ссылок, живых прототипов и замыканий, которые V8 ошибочно считает нужными.
Прототипы и скрытые классы
У каждого объекта в V8 есть скрытый класс (HiddenClass) и ссылка на прототип. Пока жив экземпляр, весь прототип со всеми методами и данными остаётся в памяти. Это особенно критично для утечек через кеши:
function Data(id) {
this.id = id;
this.buffer = new ArrayBuffer(100);
}
const obj = new Data(1);
// Если obj утёк через замыкание — Data.prototype не соберётся GCЗамыкания и живые контексты
V8 оптимизирует замыкания, но ошибается: если внутри замыкания объявлена большая переменная, а используется только часть контекста, GC всё равно держит всю аллокацию:
function createProcessor() {
const hugeData = new ArrayBuffer(500); // утечка
return {
process: () => console.log('ok'),
release: () => {}
};
}
// Пока жив processor, hugeData не соберётсяНеявные ссылки через WeakMap и Symbol.species
Слабая карта не гарантирует сборку — если ключ жив, значение тоже живёт. Symbol.species в подклассах может создать неявную ссылку на конструктор, удерживая целый прототип. Типичная ошибка — использовать Map для кеша, когда нужно WeakMap.
Что делать в production:
* Для кеширования используй WeakMap, а не Map — это единственный безопасный способ.
* В замыканиях явно зануляй большие объекты:
hugeData = null после создания.* Снимай heap snapshots через
node --inspect или Chrome DevTools — ищи пачки объектов с одинаковым прототипом.* После создания массива экземпляров можно занулить
Constructor.prototype.constructor = null — это ломает ссылку на конструктор, но рискованно.Вывод:
Одна невидимая ссылка через прототип или замыкание может закрепить сотни мегабайт в куче — используй WeakMap, явное зануление и профилирование, чтобы production не упал по памяти.
Forwarded from Dezzigners
🧰 Origin Coffee Mockup — набор из 7 качественных мокапов, с помощью которых вы можете презентовать дизайн кофейного бренда
Cкачать
Dezzigners
Cкачать
Dezzigners
Forwarded from PSD | Дизайн-пространство
This media is not supported in your browser
VIEW IN TELEGRAM
Day 474:
SLAPS An independent creative company.
→ brandingthatslaps.com
Workflow The simplest way to manage creative work.
→ workflow.design
More on
→ curated.design
SLAPS An independent creative company.
→ brandingthatslaps.com
Workflow The simplest way to manage creative work.
→ workflow.design
More on
→ curated.design
Forwarded from Daily Coding 🔥
🛠 Devices.css - библиотека, в которой представлены современные мобильные устройства, созданные с использованием чистого CSS. В нее входят некоторые из самых популярных мобильных устройств, таких как iPhone X, Google Pixel 2 XL и Samsung Galaxy S8. Дизайн отличается элегантностью и высоким качеством и может быть использован для создания целевых страниц или скриншотов.
🌍 Сайт
Daily Coding #инструменты #CSS & Max
🌍 Сайт
Daily Coding #инструменты #CSS & Max
Forwarded from Node.JS [ru] | Серверный JavaScript
Atomics.wait заблокировал event loop — как не убить Node.js в production
Общая память через
Как блокировка ломает Event Loop
Когда worker вызывает
Production-сценарий: дедлок коммуникации
Часто main thread посылает worker задачу и ждёт ответа через
Типичная ошибка: забыть про альтернативы
Многие пишут
Практический совет:
Используйте экспериментальный
Вывод:
Общая память через
SharedArrayBuffer даёт мощную межпоточную синхронизацию, но некорректное использование Atomics.wait в worker_threads способно полностью парализовать приложение. Частая ошибка: разработчики забывают, что Atomics.wait — синхронный блокирующий вызов, который останавливает весь поток, включая event loop.Как блокировка ломает Event Loop
Когда worker вызывает
Atomics.wait(buf, 0, 0), он зависает, пока другой поток не изменит значение. В main thread такой вызов выбрасывает TypeError, но внутри worker это законно. Поток перестаёт обрабатывать сообщения и таймеры — worker становится мёртвым.Production-сценарий: дедлок коммуникации
Часто main thread посылает worker задачу и ждёт ответа через
postMessage. Если worker перед этим вызвал Atomics.wait и заблокировался — ответ никогда не придёт. Приложение зависает без краша или явной ошибки.// worker.js
const { parentPort, workerData } = require('worker_threads');
const sab = new SharedArrayBuffer(4);
const view = new Int32Array(sab);
Atomics.wait(view, 0, 0); // Worker hangs forever
parentPort.postMessage('done'); // Never reached
Типичная ошибка: забыть про альтернативы
Многие пишут
Atomics.wait без таймаута или не проверяют, что воркеры уже заняты. Всегда указывайте значение таймаута: Atomics.wait(buf, 0, 0, 1000) — хотя бы не бесконечное ожидание.Практический совет:
Atomics.waitAsync или изоляцияИспользуйте экспериментальный
Atomics.waitAsync() для неблокирующего ожидания. Либо выносите всю логику блокирующих вызовов в отдельные воркеры, которые общаются только через Atomics.store и Atomics.load без синхронных ожиданий.Вывод:
Atomics.wait в worker_threads может полностью убить event loop, если не контролировать время блокировки или связь с main thread.