Библиотека сайта rus-linux.net
Система обмена сообщениями ZeroMQ
Глава 24 из книги "Архитектура приложений с открытым исходным кодом", том 2.Оригинал: "ZeroMQ".
Автор: Martin Sústrik, перевод: Н.Ромоданов
24.4. Критический путь
Мы в процессе оптимизации обнаружили , что на производительность оказывают решающее влияние следующие три фактора:
- Количество операций выделения памяти
- Количество системных вызовов
- Модель распараллеливания
Однако не каждая операция выделения памяти и не каждый системный вызов оказывает одинаковое влияние на производительность. Характеристикой, которая нас интересует в системах обмена сообщениями, является количество сообщений, которое мы можем передать между двумя конечными точками в течение определенного количества времени. Кроме того, нас может интересовать то, как долго сообщение передается из одной точки в другую.
Но, учитывая то, что ØMQ предназначена для сценариев с долгоживущими соединениями, время, необходимое для установления соединения или время, необходимое для обработки ошибки соединения, в основном, значения не имеет. Эти события происходят очень редко, и поэтому их влияние на общую производительность незначительно.
Та часть кода, которая снова и снова используется очень часто, называется критическим путем (critical path); оптимизировать следует критический путь.
Давайте рассмотрим пример: библиотека ØMQ не очень оптимизирована относительно выделения памяти. Например, при обработке строк, она часто выделяет новую строку для каждого промежуточного этапа преобразования. Тем не менее, если мы посмотрим строго на критический путь, т. е. фактическую передачу сообщений, мы увидим, что в библиотеке практически не происходит выделение памяти. Если сообщения небольшие, то это всего лишь одно выделение памяти на 256 сообщений (эти сообщения хранятся в одном большом выделенном участке памяти). Если, кроме того, поток сообщений устойчив и без огромных пиков трафика, то количество выделений памяти на критическом пути падает до нуля (выделенные участки памяти не возвращаются, но снова и снова используются повторно).
Усвоенный урок: Есть разница в том, где выполнять оптимизацию. Оптимизация фрагментов кода, которые не находятся на критическом пути, является напрасной тратой усилий.
24.5. Выделение памяти
Если предположить, что вся инфраструктура инициализирована и соединение между двумя конечными точками уже установлено, есть только одно, для чего выделяется память, это - само сообщение. Таким образом, для оптимизации критического пути мы должны были изучить, как происходит выделение памяти под сообщения и как сообщения передаются вверх и вниз по стеку.
В сфере высокопроизводительных сетей общеизвестно, что лучшая производительность достигается за счет четкого баланса между стоимостью выделения памяти под сообщение и стоимостью копирования сообщения (например, http://hal.inria.fr/docs/00/29/28/31/PDF/Open-MX-IOAT.pdf: сравните различные подходы для «малых», «средних» и «больших» сообщений). Для небольших сообщений, копирование гораздо дешевле, чем выделение памяти. Имеет смысл вообще не выделять никаких новых кусков памяти, а вместо этого по мере необходимости копировать сообщение в заранее выделенную память. Для больших сообщений, с другой стороны, копирование гораздо дороже, чем выделение памяти. Имеет смысл один раз выделить память для сообщения и, вместо копирования данных, передать указатель на выделенный блок. Такой подход называется «нулевым копированием».
ØMQ обрабатывает оба варианта прозрачно. Сообщение ØMQ представлено структурой, в которой спрятаны детали. Содержимое очень маленьких сообщений хранится непосредственно в структуре. Таким образом, при создании копии структуры действительно копируется данные сообщения. Когда сообщение станет большим, для него выделяется отдельный буфер, а в структуре хранится только указатель на буфер. Создание копии структуры не приводит к копированию данных сообщения, что разумно в случае, когда размер сообщения равен мегабайтам (рис. 24.3). Следует отметить, что в последнем случае в буфере подсчитывается количество указателей, так что можно использовать указатели из нескольких структур и не требуется копировать данные.
Рис.24.3: Копирование сообщения (или только указателя)
Усвоенный урок: Когда вы думаете о производительности, то не считайте, что наилучшее решение только одно. Может случиться, что есть несколько подклассов проблемы (например, небольшие сообщения и большие сообщения), для каждого из которых есть свой собственный оптимальный алгоритм.
Далее: 24.6. Пакетная обработка