Zero-copy в Linux. Как работает sendfile, mmap и почему это быстрее

6 минут чтения
Средний рейтинг статьи — 4.6

Когда приложение передаёт данные — например, отдаёт файл по HTTP — данные обычно проходят несколько этапов копирования:

  1. диск → kernel space
  2. kernel → user space
  3. user space → kernel
  4. kernel → сеть

Каждое копирование — это лишняя нагрузка на CPU и память. В высоконагруженных системах это становится узким местом.

Zero-copy — это подход, который позволяет минимизировать или полностью убрать лишние копирования.

Почему копирование — это дорого

При каждом copy происходит:

  • загрузка данных в CPU cache
  • перемещение между буферами
  • переключение контекста (syscalls)

Это приводит к:

  • увеличению CPU usage
  • росту latency
  • снижению throughput

Особенно критично при работе с большими файлами и большим количеством соединений.

Что такое zero-copy

Zero-copy — это техника, при которой данные не копируются между user space и kernel space без необходимости.

Идея:

  • данные остаются в kernel
  • приложение только управляет передачей

Результат:

  • меньше копий
  • меньше syscalls
  • выше производительность

sendfile

sendfile() — один из самых известных zero-copy механизмов.

Он позволяет передать данные напрямую:

file → socket

без промежуточного копирования в user space.

Как работает

Обычный путь:

read() → user buffer → write()

С sendfile:

kernel buffer → socket

Пример:

sendfile(out_fd, in_fd, NULL, size);

Где используется

  • Nginx
  • Apache
  • файловые серверы

Плюсы

  • меньше CPU
  • меньше копирования
  • выше throughput

mmap

mmap() отображает файл в память процесса.

Вместо чтения файла через read, вы работаете с ним как с обычным массивом.

Как работает

  • файл отображается в виртуальную память
  • данные подгружаются по мере доступа (page fault)

Пример:

void* data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);

Особенности

  • нет явного копирования
  • ленивое чтение
  • работа через page cache

Когда это быстрее

  • случайный доступ к файлам
  • большие файлы

Минусы

  • сложнее управление памятью
  • возможны page faults (латентность)

sendfile vs mmap

Параметрsendfilemmap
Основной кейсfile → socketработа с файлами
Копированиеминимальноеотсутствует явно
Контрольпростой APIбольше контроля
Использованиевеб-серверыбазы данных, кеши

Дополнительные механизмы

splice

Позволяет передавать данные между файловыми дескрипторами через pipe без копирования.

fd → pipe → fd

sendfile + page cache

Важно понимать:

  • данные всё равно проходят через page cache
  • но не копируются в user space

Почему это быстрее

  1. Меньше копирований
  2. Меньше syscalls
  3. Меньше нагрузки на CPU cache
  4. Эффективное использование page cache

В реальности это даёт:

    • throughput
    • latency
    • CPU usage

Когда zero-copy особенно важен

  • CDN
  • веб-серверы (Nginx)
  • стриминг
  • прокси (HAProxy)

Ограничения

  • не всегда применим (например, когда нужно модифицировать данные)
  • зависит от ОС и файловой системы
  • требует понимания работы kernel

Практические советы

  1. Используйте sendfile для отдачи файлов
  2. mmap — для сложной работы с файлами
  3. избегайте лишних read/write
  4. профилируйте CPU и syscalls

Итог

Zero-copy — это мощная оптимизация для систем с большим объёмом I/O.

  • sendfile ускоряет передачу файлов в сеть
  • mmap упрощает работу с данными в памяти

Если упрощать:

  • меньше копий → меньше нагрузки → выше скорость

Понимание этих механизмов позволяет строить более эффективные и масштабируемые системы.

6 минут чтения
Средний рейтинг статьи — 4.6

Настроить мониторинг за 30 секунд

Надежные оповещения о даунтаймах. Без ложных срабатываний