предисловие
Три слова «нулевая копия» наверняка слышали многие из вас.Эта технология используется в различных компонентах с открытым исходным кодом, таких как kafka, RocketMQ, Netty, nginx и других фреймворках с открытым исходным кодом. Итак, сегодня я хочу поделиться с вами некоторыми знаниями о нулевом копировании.
передача данных в компьютер
Прежде чем представить нулевое копирование, я хочу поговорить о том, как данные передаются в компьютерной системе. При разработке системы передачи данных, ради написания этой части, я пожертвовал принципом компьютерной композиции, который я вытирал много лет:
Ранняя стадия:
Разбросанные соединения, серийная работа, программные запросы. На этом этапе ЦП выступает в роли няни и должен считывать данные с интерфейса ввода-вывода, а затем отправлять их в основную память.
- CPU активно запускает устройство ввода/вывода
- Затем ЦП продолжает спрашивать старое железо устройства ввода-вывода, готовы ли вы.Обратите внимание, что это всегда спрашивает.
- Если устройство ввода-вывода сообщает ЦП: я готов. CPU считывает данные с интерфейса ввода/вывода.
- Затем ЦП продолжает передавать эти данные в основную память, как курьер.
Этот неэффективный процесс передачи данных занимает ЦП, а ЦП не может выполнять другие более значимые действия.
Интерфейсный модуль и каскад прямого доступа к памяти
Эту часть мы также обсудим позже.
интерфейсный модуль
В структуре фон Неймана каждый компонент имеет отдельное соединение, которое является не только первым, но и затрудняет расширение устройств ввода-вывода.Ранний этап выше — это система, которая называется децентрализованным соединением. Расширение устройства ввода-вывода требует подключения большого количества проводов. Поэтому вводится метод подключения к шине, и несколько устройств подключаются к одной и той же группе шин для формирования общего канала передачи между устройствами.
В этом режиме обмен данными принимает метод прерывания программы.Выше мы знаем, что после того, как мы запускаем устройство ввода-вывода, мы спрашиваем, готово ли устройство ввода-вывода.Если этот этап удален, прерывание программы очень хорошо.Исполнилось наше давнее желание:
- CPU активно запускает устройство ввода/вывода.
- После запуска ЦП нет необходимости снова запрашивать ввод-вывод, и он начинает делать другие вещи, похожие на асинхронность.
- После того, как ввод-вывод готов, сообщите ЦП, что я готов, через прерывание шины.
- ЦП считывает данные и передает их в оперативную память.
DMA
Хотя вышеописанный метод улучшает коэффициент использования ЦП, ЦП все еще занят во время прерывания.Для дальнейшего решения проблемы занятости ЦП вводится метод DMA.В методе DMA основная память и устройство ввода/вывода Существует канал передачи данных, поэтому при обмене данными между оперативной памятью и устройствами ввода-вывода нет необходимости снова прерывать ЦП.
Вообще говоря, нам нужно обратить внимание только на DMA и прерывания.Ниже приведены некоторые из них, подходящие для больших компьютеров.Вот краткое введение:
сцена с канальной структурой
В небольших компьютерах DMA можно использовать для реализации обмена данными между высокоскоростными устройствами ввода-вывода и хостом, однако в больших и средних компьютерах существует множество конфигураций ввода-вывода, и передача данных является тривиальной. DMA используется, будет ряд проблем.
- Каждое устройство ввода-вывода конфигурируется с выделенным интерфейсом DMA, что не только увеличивает стоимость оборудования, но и решает проблему конфликтов доступа DMA и ЦП, что очень усложняет управление.
- Процессору необходимо управлять многочисленными DMA-интерфейсами, что также влияет на эффективность работы.
Поэтому вводится канал.Канал используется для управления устройством ввода/вывода и компонентами, которые обмениваются информацией между основной памятью и устройством ввода/вывода.Его можно рассматривать как процессор со специальными функциями. Это выделенный процессор, подчиненный ЦП, который не принимает непосредственного участия в управлении, поэтому использование ресурсов ЦП улучшается.
Этапы с обработчиками ввода/вывода
Система ввода-вывода развилась до четвертой стадии, появился процессор ввода-вывода. Процессор ввода-вывода, также известный как периферийный процессор, работает независимо от хоста и может не только выполнять управление вводом-выводом, которое должно выполняться каналом ввода-вывода, но также выполнять обработку формата, исправление ошибок и другие операции. операции. Система вывода с процессором ввода-вывода имеет более высокую степень параллелизма с работой ЦП, что означает, что система ввода-вывода имеет большую независимость от хоста.
резюме
Мы видим, что целью эволюции передачи данных было снижение использования ЦП и улучшение использования ресурсов ЦП.
копия данных
Давайте сначала представим наши сегодняшние потребности.На диске есть файл, и теперь его нужно передать по сети. Если да, то что делать? Я считаю, что благодаря некоторым из приведенных выше вступлений у вас должны появиться некоторые идеи.
традиционная копия
Если мы реализуем его в коде Java, у нас будет следующая реализация: Ссылка на псевдокод выглядит следующим образом:
public static void main(String[] args) {
Socket socket = null;
File file = new File("test.file");
byte[] b = new byte[(int) file.length()];
try {
InputStream in = new FileInputStream(file);
readFully(in, b);
socket.getOutputStream().write(b);
} catch (Exception e) {
}
}
private static boolean readFully(InputStream in, byte[] b) {
int size = b.length;
int offset = 0;
int len;
for (; size > 0;) {
try {
len = in.read(b, offset, size);
if (len == -1) {
return false;
}
offset += len;
size -= len;
} catch (Exception ex) {
return false;
}
}
return true;
}
Это наш традиционный метод копирования.Конкретная схема потока данных выглядит следующим образом, PS: Здесь не рассматривается, что данные в куче нужно копировать в прямую память при передаче данных в Java.
Видно, что нашему менеджеру нужно пройти четыре этапа, 2 DMA, 2 прерывания ЦП, всего четыре копии, четыре переключения контекста, и он будет занимать два ЦП.
- ЦП отправляет инструкции DMA устройства ввода-вывода, а DMA передает данные с нашего диска в буфер ядра в пространстве ядра.
- Второй этап запускает прерывание ЦП, и ЦП начинает копировать данные из буфера ядра в кеш нашего приложения.
- ЦП копирует данные из кеша приложения в буфер сокета в ядре.
- DMA копирует данные из буфера сокета в буфер сетевой карты.
Достоинства: низкая стоимость разработки, подходит для некоторых невысоких требований к производительности, например некоторых систем управления, думаю должно хватить
Недостатки: несколько переключений контекста, использование нескольких процессоров и низкая производительность.
sendFile реализует нулевое копирование
Как насчет нулевой копии выше? Позиционирование в вики: обычно относится к тому, что когда компьютер отправляет файл по сети, ему не нужно копировать содержимое файла в пространство пользователя (User Space) и напрямую передает его в сеть в пространстве ядра ( пространство ядра).
В java NIO FileChannal.transferTo() реализует sendFile операционной системы, мы можем выполнить вышеуказанные требования с помощью следующего псевдокода:
public static void main(String[] args) {
SocketChannel socketChannel = SocketChannel.open();
FileChannel fileChannel = new FileInputStream("test").getChannel();
fileChannel.transferTo(0,fileChannel.size(),socketChannel);
}
Мы заменили наш сокет и fileInputStream выше каналом в java.nio, тем самым завершив нашу нулевую копию.
Вышеупомянутый конкретный процесс выглядит следующим образом:
- Когда вызывается sendfie(), ЦП отправляет инструкцию, называемую DMA, для копирования данных с диска в буфер ядра.
- После завершения копирования DMA выдается запрос на прерывание, а ЦП копируется и копируется в буфер сокета. Вызов sendFile завершается и возвращается. 3. DMA копирует буфер сокета в буфер сетевой карты.
Вы можете видеть, что мы вообще не копировали данные в кеш нашего приложения, поэтому этот подход является нулевым копированием. Тем не менее, этот метод по-прежнему очень болезненный, хотя он сводится всего к трем копиям данных, он по-прежнему требует от ЦП прерывания копирования данных. Зачем? Потому что DMA должен знать адрес памяти, прежде чем я смогу отправить данные. Поэтому в ядро Linux 2.4 были внесены улучшения, и соответствующая информация описания данных (адрес памяти, смещение) в буфере ядра записывается в соответствующий буфер сокета. В итоге формируется следующий процесс:
Таким образом, ЦП не участвует в копировании всего процесса, поэтому эффективность является наилучшей.
Подобные коды есть в Netty, RocketMQ и kafka в сторонних фреймворках с открытым исходным кодом, если интересно, можете поискать самостоятельно.
сопоставление mmap
Мы упомянули о реализации нулевого копирования выше, но мы можем только отправить данные пользователю в неповрежденном виде и не можем использовать их сами. Поэтому Linux предоставляет специальный способ доступа к дисковым файлам, который может связать определенное адресное пространство в памяти с дисковым файлом, который мы хотим указать, чтобы преобразовать наш доступ к этой памяти в доступ к дисковым файлам. Отображение. Мы используем эту технологию, чтобы напрямую сопоставить файл с адресом памяти пользовательского режима, так что операция с файлом больше не является записью/чтением, а напрямую оперирует адресом памяти.
Полагаясь на MappedByteBuffer для сопоставления mmap в Java, конкретный MappedByteBuffer может обратиться к этой статье за подробностями:Woohoo.Краткое описание.com/afraid/send 90866 low cost….
Наконец
С тех пор тайна нулевого копирования также была раскрыта.Нулевое копирование предназначено только для уменьшения использования ЦП и позволяет ЦП выполнять более реальные бизнес-задачи. Благодаря этой статье вы можете увидеть, как Нетти делает нулевое копирование, я думаю, это произведет более глубокое впечатление.
Наконец, эта статья была включена в JGrowing, всеобъемлющий и отличный маршрут изучения Java, совместно созданный сообществом.Если вы хотите участвовать в обслуживании проектов с открытым исходным кодом, вы можете создать его вместе.Адрес github:GitHub.com/Java растет…Пожалуйста, дайте мне маленькую звезду.
Если вы считаете, что эта статья полезна для вас, или если у вас есть какие-либо вопросы и вы хотите предоставить бесплатный VIP-сервис 1 на 1, вы можете подписаться на мой официальный аккаунт Ваше внимание и пересылка - самая большая поддержка для меня, O(∩_∩)O :