TGViewer
Настя Котова // Frontend & Node.js Настя Котова // Frontend & Node.js @startpoint_dev · 1.41K subscribers
Post #210 1.7K
Продолжаю про работу с сырыми данными. В этот раз — про Buffer.

Buffer — это Node.js-специфичная вещь, в браузере его нет. Технически он наследуется от Uint8Array, то есть это тот же TypedArray, но с дополнительными методами для удобной работы со строками и файлами:


const b = Buffer.from('hello', 'utf8');
b.toString('hex'); // '68656c6c6f'


У Buffer есть три статических метода для аллокации, и они работают принципиально по-разному.

Buffer.alloc(size) — безопасный вариант. Создаёт отдельный ArrayBuffer нужного размера, память заполняется нулями. Пул не используется.


Buffer.alloc(8); // <Buffer 00 00 00 00 00 00 00 00>


Buffer.allocUnsafe(size) — быстрый вариант. Память не обнуляется, в буфере могут быть остатки старых данных. Но самое интересное — это то, как он выделяет память.

Buffer.allocUnsafeSlow(size) — как allocUnsafe, но всегда создаёт отдельный ArrayBuffer, без пула. Зачем — объясню ниже.

Когда вы вызываете Buffer.allocUnsafe(100), Node.js не идёт каждый раз просить систему выделить 100 байт. Вместо этого он заранее выделяет один большой кусок памяти на 8 КБ (пул) и нарезает от него маленькие буферы:

Если запрошенный размер меньше 4096 байт (половина от размера всего пула), Node.js просто двигает указатель внутри пула и создаёт новый view на уже существующий ArrayBuffer. Новой аллокации памяти нет, поэтому это очень быстро.

Если в текущем пуле не хватает места — создаётся новый. Если запрошенный буфер слишком большой (≥ 4096) — пул не используется, создаётся отдельный ArrayBuffer.

Порог в половину пула выбран не случайно: если буфер занимает больше половины, он съест почти весь пул, а оставшийся хвост станет бесполезным.

После каждой нарезки poolOffset выравнивается до границы в 8 байт. Это нужно для производительности: невыровненный доступ к памяти на некоторых архитектурах медленнее.

Все маленькие буферы, нарезанные из одного пула, разделяют один ArrayBuffer. Это значит: пока хотя бы один такой буфер жив, все 8 КБ пула не могут быть собраны GC.

Именно для этого существует Buffer.allocUnsafeSlow(size) — он всегда создаёт отдельный ArrayBuffer. Если вы создаёте много маленьких буферов и удерживаете их надолго (кешируете, складываете в массив), allocUnsafeSlow может быть экономичнее по памяти.
  • ❤ 11
  • 👍 5
  • ⚡ 2
  • 🔥 1
More from @startpoint_dev
  1. Sep 21, 2026Я к вам с новым анонсом. Этот год я заканчиваю выступлением на HolyJS! Конференция пройдёт…
  2. Sep 14, 2026В прошлый раз разбирали, зачем нужны using и await using и где они работают. Теперь посмот…
  3. Sep 7, 2026В JavaScript регулярно появляются новые возможности, и не про все из них мы вообще узнаём.…
  4. Aug 31, 2026В цикле про рендеринг мы разбирали конвейер: стили, лейаут, отрисовка, композитинг. Всё эт…
  5. Aug 24, 2026Весной мы обсуждали работу с сырыми данными: ArrayBuffer, Buffer в Node.js, SharedArrayBuf…
  6. Aug 17, 2026Когда я готовила материал для цикла про Next.js, то неожиданно для себя узнала, что в нём…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →