DMA и технология нулевого копирования для оптимизации передачи больших файлов по сети
DMA и технология нулевого копирования для оптимизации передачи больших файлов по сети
Разработка контроллеров DMA
Нет процесса ввода-вывода контроллера DMA
Пользовательский процесс запущен read вызов,КОперационная системаотправлять I/O Запрос, процесс переходит в состояние блокировки;
Операционная После того, как система получит запрос на прибытие, ЦП Выдайте соответствующие команды управления контроллеру диска, CPU Выпущен для выполнения других задач.
После того как контроллер диска получает инструкцию, он начинает готовить данные и помещает их во внутренний буфер контроллера диска, а затем генерирует прерывание.
После того, как ЦП получает сигнал прерывания, он считывает данные из буфера контроллера диска в регистр, а затем записывает их из регистра в буфер ядра. Во время этого процесса ЦП не может обрабатывать другие вещи.
Когда в буфере ядра достаточно данных, ЦП копирует данные из буфера ядра в пользовательский буфер.
контроллер прямого доступа к памяти
если CPU Передаваемые данные очень малы, поэтому проблема невелика, но если вам нужно скопировать большой объем данных, это точно невозможно, потому что CPU ресурсы очень ценны. Для решения этой проблемы появились DMA(Direct Memory Доступ, прямой доступ к памяти) технология.
Проще говоря: в процессе I/O При передаче данных между устройствами и памятью вся работа по обработке данных передается контроллер прямого доступа к памяти,и CPU Больше не участвуйте ни в чем, связанном с передачей данных, поэтому CPU Потом можешь пойти заняться другими делами.
использовать контроллер прямого доступа к После запоминания процесс передачи данных выглядит следующим образом:
Пользовательский процесс запущен read вызов,КОперационная системаотправлять I/O Запрос, процесс переходит в состояние блокировки;
Операционная После того, как система получит запрос на прибытие, ЦП Отправить запрос на DMA , CPU Выпущен для выполнения других задач.
DMA дальше I/O Запрос на отправку дискового контроллера, После того как контроллер диска получает инструкцию, он начинает готовить данные и помещает их во внутренний буфер контроллера диска, а затем генерирует прерывание.
После получения сигнала прерывания DMA копирует данные из буфера контроллера диска в кэш ядра (ресурсы ЦП в это время не заняты, и ЦП может выполнять другие задачи).
Когда DMA считывает достаточно данных в буфер ядра, он отправляет сигнал прерывания в ЦП, и ЦП копирует данные из буфера ядра в пользовательский буфер.
Язык кода:txt
копировать
Примечание: рано DMA Только держисуществоватьна материнской плате,сейчассуществовать I/O Устройств становится все больше, а требования к передаче данных становятся все более сложными, поэтому каждое I/O Каждое устройство имеет свой собственный контроллер прямого доступа к памяти。
Насколько плоха традиционная производительность передачи файлов?
сейчассуществовать,Подумайте об этом, все,если на нашем сервере должна быть предусмотрена функция передачи файлов,Что следует сделать? Самый простой способ — прочитать файл на диске.,Затем отправляется клиенту по сетевому протоколу. Обычно задействованы следующие два системных вызова:
Давайте посмотрим, что произошло в целом в процессе. Было 2 системных вызова (4 переключения контекста) и 4 копии данных (2 копии CPU, 2 копии DMA).
Хотя время переключения контекста очень короткое и составляет от десятков наносекунд до нескольких микросекунд, в сценариях с высоким уровнем параллелизма оно может легко повлиять на производительность. В то же время мы обнаружили, что хотя мы передали только один фрагмент данных, мы скопировали его 4 раза. Нет сомнений в том, что слишком много копий данных займут ресурсы нашего процессора.
поэтому,если Мы хотим оптимизировать весь процесс передачи файлов,Тогда основная идея оптимизации — уменьшить переключение контекста между пользовательским режимом и режимом ядра и уменьшить копирование данных.
Как оптимизировать производительность передачи файлов
Выше мы упоминали, что хотим оптимизировать весь процесс передачи файлов. Основная идея оптимизации — уменьшить переключение контекста между пользовательским режимом и режимом ядра и уменьшить количество копий данных.
Мы знаем, что переключение контекста на самом деле вызвано системными вызовами, поэтому сокращение количества системных вызовов может уменьшить переключение контекста. В то же время в сценарии передачи файлов наш пользовательский процесс не обрабатывает данные, поэтому нельзя ли скопировать данные в пространство пользователя? Ответ — да, поэтому нет необходимости в существовании пользовательского буфера во время передачи файлов.
Технология нулевого копирования
На основе двух вышеупомянутых пунктов оптимизации была разработана Технология нулевого копирования,Технология нулевого копирования обычно имеет следующие два решения реализации.,Давайте поговорим конкретно о том, как это уменьшает количество переключений контекста и копий данных:
Язык кода:C
копировать
mmap + write
sendfile
mmap + write
в традиционных документах IO процесссередина,мы должныиспользовать read Вызов для чтения данных из буфера ядра в область пользовательского буфера. Чтобы уменьшить накладные расходы на этом этапе, мы используем. mmap() заменять read():
Язык кода:C
копировать
buf = mmap(file, len);
write(sockfd, buf, len);
После того как пользовательский процесс вызывает метод mmap(), DMA копирует данные с диска в буфер ядра. Пользовательский процесс и ядро используют этот буфер совместно.
После того как пользовательский процесс вызывает метод read(), ЦП копирует данные из буфера ядра в буфер Socket.
sendfile
Хотя весь описанный выше процесс сокращает две копии данных, все равно остается 4 переключения контекста.
В ядре Linux версии 2.1 функция системного вызова sendfile() предусмотрена специально для отправки файлов. Форма функции следующая, что позволяет еще больше сократить системные вызовы:
Язык кода:C
копировать
#include <sys/socket.h>
// Первые два параметра — это файловый дескриптор места назначения и источника соответственно. Последние два параметра — это смещение источника и длина данных. Возвращаемое значение — это длина фактических данных.
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
Таким образом, для одной передачи файла нам понадобится всего 3 копии данных и 2 переключателя контекста.
SG-DMA(The Scatter-Gather Direct Memory Access)
если Поддержка сетевых карт SG-DMA(The Scatter-Gather Direct Memory Доступ) технологии (и общие DMA другое), sendfile() Вызов будет дополнительно оптимизирован и удален. CPU Скопируйте данные из буфера ядра в socket буферная зонапроцесс,данныепрямойкопировать из буфера ядраприезжатьсетевая картасередина。
Это настоящая технология нулевого копирование (нулевая копия), так как нам не пришлосьиспользовать на протяжении всего процесса CPU Вместо этого скопируйте данные через DMA осуществить передачу.
Технология нулевого копирования Приложение
Наши наиболее часто используемые kafka Сразуиспользовать Понятно Технология нулевого копирование, тем самым значительно улучшая I/O пропускная способность, которая также kafka Одна из причин, почему он может обрабатывать огромные объемы данных.
kafka Часть передачи реализует базовый вызов Java NIO Карри transferTo метод,если Linux Поддержка системы sendfile() системный вызов, затем transferTo() На самом деле, в конце концов придется использоватьприезжать sendfile() Функция системного вызова.
Язык кода:Java
копировать
@Overridepublic
long transferFrom(FileChannel fileChannel, long position, long count) throws IOException {
return fileChannel.transferTo(position, count, socketChannel);
}
существуют в тех же аппаратных условиях,Тест разницы в производительности традиционной передачи файлов и передачи файлов с нулевым копированием,использовать Понятно Технология нулевого копирование близко к сокращенному 65% время, что может значительно улучшить нашу пропускную способность:
Тестовые данные нулевого копирования.png
Какой метод следует использовать для передачи больших файлов?
Прежде чем разобраться в этой проблеме, мы сначала поймем две концепции. PageCache и Прямой ввод-вывод。
Роль PageCache (буфера ядра)
Буфер записи: при записи данных алгоритм ввода-вывода ядра кэширует как можно больше запросов ввода-вывода в PageCache и, наконец, объединяет их в более крупный запрос ввода-вывода на диск, сокращая операции по адресации диска.
Чтение кэша: ядро предварительно считывает соседнее содержимое данных и кэширует некоторые «горячие» данные в PageCache, сокращая доступ к диску и повышая скорость доступа.
Прямой ввод-вывод
Прямой ввод-вывод Применимые сценарии
В самом приложении реализовано кэширование дисковых данных, поэтому необходимости в PageCahe , Уменьшите потребление, вызванное копированием буфера ядра. Такие как существуют MySQL Вы можете открыть Прямой в базе данных. ввод-вывод, по умолчанию не включен.
Сами данные слишком велики, и их трудно поместить в кэш PageCahe. В то же время они занимают PageCahe, в результате чего другие «горячие» данные становятся недействительными и вызывают дополнительные издержки производительности.
В итоге
Из двух приведенных выше пунктов мы видим: Вопрос: Можно ли перемещать небольшие файлы в область кэша пользователя вместо области кэша ядра?
отвечать:
1. использовать буфер ядра При копировании данных из дискового буфера можно использовать DMA
2. Теоретически стоимость данных, попадающих в пользовательский кэш, больше, чем стоимость данных, поступающих в буфер ядра.
Для передачи небольших файлов мы можем уменьшить количество переключений контекста и копий данных и повысить производительность.
Но для больших файлов,Уже не подходит Технология нулевого копирования на основе PageCahe,и Это должно бытьиспользовать Прямой ввод-вывод Кстати, и во избежание больших файлов Прямой ввод-вывод Принося долгосрочные перегрузки, мы можем использовать Прямой ввод-вывод + асинхронный I/O способ передачи больших файлов.
Nginx серединаиз Технология нулевого копированияи Прямой ввод-вывод
существовать nginx , оба поддерживают Технология нулевого копирования,Также поддерживает Прямой ввод-вывод Мы можем настроить его в зависимости от размера файла следующим образом:
Когда размер файла меньше 1024M часиспользовать Технология нулевого копирования,когдабольше, чем когдаиспользоватьпрямой IO технология.
Профиль
👋 привет, я Lorin Лорейн, один Java Разработчик бэкэнд-технологий!девиз:Technology has the power to make the world a better place.
🚀 Моя страсть к технологиям — это моя мотивация продолжать учиться и делиться ими. Мой блог — это место об экосистеме Java, серверной разработке и последних технологических тенденциях.
🧠 Будучи энтузиастом серверных технологий Java, я не только с энтузиазмом изучаю новые возможности языка и глубину технологий, но также с радостью делюсь своими идеями и передовым опытом. Я верю, что обмен знаниями и сотрудничество с сообществом могут помочь нам расти вместе.
💡 В моем блоге вы найдете подробные статьи об основных концепциях Java, базовой технологии JVM, часто используемых платформах, таких как Spring и Mybatis, управлении базами данных, таких как MySQL, промежуточном программном обеспечении для обработки сообщений, таком как RabbitMQ и Rocketmq, оптимизации производительности и т. д. Я также поделюсь некоторыми советами по программированию и методами решения проблем, которые помогут вам лучше освоить программирование на Java.
🌐 Я поощряю взаимодействие и создание сообщества, поэтому, пожалуйста, оставляйте свои вопросы, предложения или запросы по темам и дайте мне знать, что вас интересует. Кроме того, я буду делиться последними новостями Интернета и технологий, чтобы вы всегда были в курсе последних событий в мире технологий. Я с нетерпением жду возможности вместе с вами двигаться вперед по пути технологий и исследовать безграничные возможности мира технологий.
📖 Следите за обновлениями моего блога и давайте вместе стремиться к техническому совершенству.