Поймите принцип нулевого копирования в одной статье

Java Netty
Поймите принцип нулевого копирования в одной статье

Это 12-й день моего участия в августовском испытании обновлений. Узнайте подробности события:Испытание августовского обновления

нулевая копия

Zero-Copy — этоI/OМетоды операционной оптимизации, которые быстро и эффективно перемещают данные из файловой системы в сетевой интерфейс, не копируя их из пространства ядра в пространство пользователя. ЕгоFTPилиHTTPДругие протоколы могут значительно повысить производительность. Однако следует отметить, что не все операционные системы поддерживают эту функцию, и в настоящее время толькоNIOа такжеEpollЭта функция доступна только во время передачи.

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

Проблемы с производительностью при традиционных операциях ввода-вывода

Если сервер хочет обеспечить функцию передачи файлов, самый простой способ, который мы можем придумать, — это прочитать файл на диске и отправить его клиенту по сетевому протоколу.

Традиционный ввод-вывод работает следующим образом: данные при чтении и записи копируются туда и обратно из пользовательского пространства в пространство ядра, а данные в пространстве ядра считываются или записываются с диска через интерфейс ввода-вывода на уровне операционной системы.

Код обычно выглядит следующим образом, что обычно требует двух системных вызовов:

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

Код очень простой, хотя это всего две строчки кода, но тут много чего происходит.

Во-первых, во времяПроизошло 4 переключения контекста пользовательского режима и режима ядра., потому что происходят два системных вызова, один дляread(), когда-то былwrite(), каждый системный вызов должен сначала переключаться из пользовательского режима в режим ядра, а затем переключаться из режима ядра обратно в пользовательский режим после того, как ядро ​​завершит задачу.

Стоимость переключения контекста не мала.Переключение занимает от десятков наносекунд до нескольких микросекунд.Хотя время кажется очень коротким, в сценариях с высоким параллелизмом такое время легко накапливается и увеличивается, что влияет на производительность системы.

Во-вторых, такжепроизошло 4 копии данных, две из которых являются копиями DMA, а две другие копирует ЦП.Поговорим об этом процессе:

  • 第一次拷贝, копирует данные на диск в буфер ядра операционной системы, а процесс копирования осуществляет DMA.
  • 第二次拷贝, скопируйте данные из буфера ядра в буфер пользователя, чтобы наше приложение могло использовать эту часть данных, процесс копирования завершается процессором.
  • 第三次拷贝Чтобы скопировать только что скопированные данные в пользовательский буфер, скопируйте их в буфер сокета ядра, который по-прежнему обрабатывается ЦП.
  • 第四次拷贝, скопируйте данные из буфера сокета ядра в буфер сетевой карты, и этот процесс осуществляется DMA.

Этот простой и традиционный метод передачи файлов имеет избыточное переключение контекста и копирование данных, что очень плохо в системе с высоким параллелизмом, поскольку добавляет много ненужных накладных расходов, что серьезно влияет на производительность системы.

так,Для повышения производительности передачи файлов необходимо уменьшить количество «переключений контекста между режимом пользователя и режимом ядра» и «копирования в память»..

Принципы технологии нулевого копирования

Нулевое копирование в основном используется для решения проблемы, связанной с тем, что операционная система часто копирует данные при обработке операций ввода-вывода. Основными технологиями нулевого копирования являются:mmap+write,sendfileа такжеspliceи так далее несколькими способами.

Виртуальная память

Прежде чем понять технологию нулевого копирования, сначала разберитесь с концепцией виртуальной памяти.

Все современные операционные системы используют виртуальную память, используя виртуальные адреса вместо физических, в основном для следующих преимуществ:

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

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

На следующем рисунке показан принцип работы виртуальной памяти.

image-20210812181924274

mmap/метод записи

использоватьmmap/writeСпособ замены исходного традиционного способа ввода-вывода заключается в использовании преимуществ виртуальной памяти. На рисунке ниже показаноmmap/writeпринцип:

image-20210812201839908

Основное отличие всего процесса в том, что после считывания данных в буфер ядра, когда приложение выполняет операцию записи,Read Bufferданные копируются вSocket BufferДля записи этой копии между ядрами также требуется участие ЦП.

Вышеупомянутый процесс требует на одну операцию COPY меньше CPU, что повышает скорость ввода-вывода. Однако обнаружено, что переключение контекста по-прежнему происходит в 4 раза и не уменьшилось, потому что приложение все еще должно инициироваться.writeработать.

Может ли это уменьшить переключение контекста?sendfileспособ дальнейшей оптимизации.

метод отправки файла

Начиная с Linux версии 2.1, Linux представилsendfileдля упрощения операции.sendfileспособ заменить вышеперечисленноеmmap/writeспособ дальнейшей оптимизации.

sendfileсделает следующее:

  mmap();
  write();

替换为:

 sendfile();

Это уменьшает переключение контекста, поскольку инициирует на одно приложение меньше.writeоперация, непосредственно инициированнаяsendfileработать.

На рисунке ниже показаноsendfileпринцип:

image-20210812201905046

sendfileЕсть только три копии данных (из которых есть только одна CPU COPY) и 2 контекстных переключателя.

Можно ли свести CPU COPY на нет? Это требуетscatter/gatherизsendfileтоже.

метод sendfile с разбросом/сбором

Ядро Linux 2.4 оптимизировано для обеспеченияscatter/gatherоперация sendfile, которая принимает последнийCPU COPYУдалить. Принцип заключается в том, что буфер чтения и буфер сокета в пространстве ядра не копируют данные, а записывают адрес памяти и смещение буфера чтения в соответствующий буфер сокета, так что копирование не требуется. Суть его та же, что и решения виртуальной памяти, то есть записи адреса памяти.

На следующем рисунке показан принцип отправки файла scatter/gather:

image-20210812201922193

Файл отправки scatter/gather имеет только две копии данных (обе DMA COPY) и два переключения контекста. CUP COPY полностью исчезла. Однако для этой функции сбора и репликации требуется поддержка оборудования и драйверов.

путь сращивания

spliceпозвони иsendfileТочно так же пользовательское приложение должно иметь два дескриптора открытых файлов, один для устройства ввода и один для устройства вывода. а такжеsendfileразница в том,spliceПозволяет связать любые два файла друг с другом, а не толькоsocketПередача данных. Для отправки данных из файлового дескриптора вsocketВ этом особом случае он всегда использовалсяsendfileсистемный вызов, покаspliceОн всегда был просто механизмом, он не ограничивалсяsendfileфункция. То есть sendfile является подмножеством splice.

В Linux версии 2.6.17 был введен splice, а в Linux версии 2.6.23 исчезла реализация механизма sendfile, но его API и соответствующие функции остались, но API и соответствующие функции используют механизм splice для реализации .

В отличие от sendfile, splice не требует аппаратной поддержки.

Суммировать

Будь то традиционный метод ввода-вывода или после введения нулевого копирования, 2 разаDMA copyнезаменимы. Потому что оба DAME сделаны аппаратным обеспечением. Следовательно, так называемая нулевая копия состоит в том, чтобы уменьшить копию CPU и уменьшить переключение контекста.

На рисунке ниже показано сравнение различных технологий нулевого копирования:

Копия процессора Копия прямого доступа к памяти системный вызов переключатель контекста
традиционный метод 2 2 read/write 4
карта памяти 1 2 mmap/write 4
sendfile 1 2 sendfile 2
scatter/gather copy 0 2 sendfile 2
splice 0 2 splice 0

конец

Я кодер, которого бьют, и я пытаюсь двигаться вперед. Если статья была вам полезна, не забудьте поставить лайк и подписаться, спасибо!