
Во времена господства электромеханических устройств хранения данных, влиянием вычислительной платформы на производительность дисковых операций зачастую пренебрегали, поскольку главные потери времени были обусловлены позиционированием магнитных головок и ожиданием появления требуемого сектора. Стремительная эволюция твердотельных устройств и появление, в частности, Intel Optane сделало данный стереотип безнадежно устаревшим.
Базовые теоретические сведения
Напомним, выполнение операции чтения или записи информации mass storage устройством состоит из следующих фаз:
- Передача команды от CPU к накопителю. Центральный процессор подготавливает в оперативной памяти командную информацию и данные, необходимые для выполнения команды устройством. После этого CPU запускает накопитель, циклом записи в его командный регистр.
- Выполнение команды. Данные передаются между накопителем и оперативной памятью в режиме bus master без участия центрального процессора.
- Передача статуса от устройства к CPU. После завершения выполнения команды, необходимо сообщить о ее результатах программному обеспечению, управляющему обменом информацией (драйверу). Как правило, для этого используется механизм аппаратных прерываний, подразумевающий асинхронный запуск процессором процедуры обработки события.
Пример упрощен и не учитывает формирование очередей из нескольких запросов.
IRQ vs MSI
Задолго до появления SSD, со времен перехода на стандарт Serial ATA и контроллер AHCI (Advanced Host Controller Interface), использование выделенных сигнальных линий (IRQ) для передачи запросов на прерывание перешло в статус антикварного решения. В современных системах применяются прерывания, передаваемые сообщениями или Message Signaled Interrupts (MSI). При этом устройство, инициирующее запрос, выполняет цикл записи в специальную область памяти, адресованный контроллеру Advanced Programmable Interrupt Controller (APIC).
Interrupts vs Polling
Сигнализация об асинхронных событиях (в нашем примере завершении выполнения дисковой операции) посредством запроса на прерывание является эффективным инструментом параллельного асинхронного выполнения ввода-вывода, поскольку центральный процессор избавлен от необходимости выполнять Polling, а именно периодически опрашивать устройство на предмет определения его готовности.
Недостатком является увеличение латентности (времени реакции на событие), поскольку обработка прерывания является сравнительно долгой операцией. Ситуация усугубляется тем, что как правило, процедуры обработки прерываний выполняются кодом ядра ОС, а фоновая или прерываемая задача является пользовательским приложением, поэтому переключение требует основательной перезагрузки контекста CPU.
Interrupts vs Polling в контексте Intel Optane
Сравним тайминги выполнения операции NVMe-накопителем для асинхронного режима с использованием прерываний (interrupts) и синхронного режима, основанного на ожидании с циклическим опросом состояния (polling).
Рис.1. Диаграммы последовательностей событий при выполнения команд NVMe-устройством, для асинхронного (interrupt, верхняя диаграмма) и синхронного (polling, нижняя диаграмма) режимов выполнения
Примечание: Значения оценочные для типовой современной платформы, пример взят из документа Рика Коулсона (Rick Coulson) 3D XPoint Technology Drives System Architecture.
Для обеих диаграмм, пунктирная горизонтальная линия означает выполнение программы в режиме пользователя (Ring 3), сплошная линия означает выполнение в привилегированном режиме (Ring 0), второй вариант используется для процедуры обработки прерывания и низкоуровневых подпрограмм драйвера.
1) Верхняя диаграмма, асинхронный вариант с прерываниями.
Интервал Ta' отсчитывается от входа в подпрограмму драйвера до передачи команды NVMe-устройству. Спустя интервал Tb, процессор освобождается для выполнения фоновых задач и управление возвращается в пространство пользователя, свободного времени на это в данном примере около 2.7 микросекунды. Затем, NVMe-устройство, завершив выполнение операции, генерирует запрос на прерывание, обработка которого выполняется в интервале Ta''. После этого, управление снова возвращается в пространство пользователя, операция завершена.
2) Нижняя диаграмма, синхронный вариант с циклическим опросом готовности. В этом случае операция выполняется быстрее, но без возможности параллельной обработки фоновой задачи.
Этот вариант предельно прост, здесь отсутствует асинхронный запуск процедур а количество переключений между пространствами пользователя и ядра минимально (только при входе и выходе из подпрограммы драйвера, точки System call, Return to user). Запустив операцию на устройстве, драйвер начинает циклический опрос (интервал Polling), через 2.9 микросекунд бит готовности устанавливается, процессор выходит из цикла ожидания, процедура завершается.
Резюме
Согласно документу, синхронный режим выполнения команды накопителем с программным циклом ожидания готовности устройства, в данном примере обеспечил меньшую латентность (4.4 микросекунды против 9.0). Кроме того, преимущество параллелизма, присущее асинхронному выполнению, уменьшается пропорционально снижению латентности устройства, поскольку в случае быстрого ответа накопителя, уменьшается количество работы, которую можно выполнить за время ожидания запроса на прерывание.
На основании сказанного, разработчикам драйверов можно порекомендовать проанализировать возможность использования синхронного режима для обработки одиночных запросов к NVMe-устройству при выполнении операций с небольшими блоками типовым размером 4 килобайта, особенно в случаях, когда минимизация времени обработки заданного запроса важнее, чем возможность параллельного выполнения других задач в ожидании его результата.