«

»

Ноя 09 2012

Сравнительное тестирование механизмов передачи сообщений в Linux

При переработке CatServerObjects столкнулся с необходимостью выбора механизма передачи сообщений между потоками приложения. Для требуемой очереди были сформированы следующие требования:

  • FIFO порядок обработки
  • Поддержка сообщений различных размеров, но с возможностью наличия верхней границы
  • Поддержка блокировки потока на время ожидания данных
  • Поддержка работы с EPoll

Рассматривались следующие варианты:

  1. UNIX-сокеты
  2. POSIX Message Queue
  3. System V IPC Message Queue
  4. Собственная реализация очереди сообщений

Вариант номер 3 пришлось сразу отбросить, т.к. он не совместим с EPoll, но в тестах он всё равно будет представлен для сравнения.

Собственная очередь сообщений

Перед создаваемой очередью сообщений ставились следующие требования:

  • Предельная быстрота при передаче указателей
  • Lockfree-алгоритм
  • FIFO порядок обработки
  • Ожидания свободного места при записи в спинлоке
  • При ожидании данных возможность ожидать как в спинлоке, так и в режиме блокировки потока
  • Поддержка работы с EPoll

Для поддержки блокировки потока для ожидания данных рассматривались 2 варианта: Futex и EventFD. Сразу стоит отметить что вариант с использованием Futex несовместим с использованием EPoll, а потому годится только для потоков обработки внутренних сообщений. Ниже приводится сравнение производительности очереди сообщения при различных методах ожидания данных:

Скорость передачи указателей созданной очередью сообщений

Все тесты были проведены 10 раз, а в таблице находятся усреднённые данные

Сразу хочется отметить что ожидание данных с помощью futex`а и spinlock`а даёт очень большой разброс в производительности. Она всегда выше чем у EventFD, но минимумы и максимумы могут различаться и в 2 раза. Т.к. эти разбросы весьма случайны, то я думаю они вызваны взаимных расположением точек выполнения у потоков во время теста.

Т.к. создаваемая очередь могла передавать только указатели то в дополнение к ней был разработан специальный пул из которого выделялась память для сообщений. Такой подход вообще имеет 2 больших плюса: отсутствие лишних копирований тела сообщения и предельное сокращение времени постановки сообщения в очередь (записывается всего 1 указатель).

Тестирование различных API

Для каждого из стандартных API предоставляемых Linux для обмена сообщениями тестировалась как передача самого сообщения, так и передача указателя на него. Использование указателя на сообщение хоть и уменьшает кол-во ненужных копирований данных, но зато даёт дополнительные расходы на выделение/освобождение памяти.

Скорость передачи сообщений различными API (1 читатель + 1 писатель)

Все тесты были проведены 5 раз, а в таблице находятся усреднённые данные

Скорость передачи сообщений различными API (2 читателя + 2 писателя)

Все тесты были проведены 5 раз, а в таблице находятся усреднённые данные

Скорость передачи сообщений различными API (3 читателя + 3 писателя)

Все тесты были проведены 5 раз, а в таблице находятся усреднённые данные

Во-первых сразу хочу отметить очень высокую цену, которую мы платим за блокирование потока при ожидании данных при большом кол-ве потоков. Во вторых нельзя не заметить, что использование указателей для стандартных интерфейсов начинает приносить стабильный прирост производительности только начиная с сообщений размером 1-2КБ.

Из полученных результатов можно сделать следующие выводы:

  • UNIX-сокеты вообще не годятся для обмена сообщениями внутри программы
  • POSIX-очереди сообщений практически идентичны SysV-очередям, но зато обладают поддержкой работы с EPoll, а кроме того, еще и приоритетами для передаваемых сообщений.
  • Использование EventFD для ожидания данных во всех случаях, кроме 1-го писателя и 1-го читателя, даёт как минимум 2-х кратный выигрыш в скорости.
  • Использование Futex не очень сильно сказывается на производительности очереди при более чем 1-м писателе и 1-м читателе
  • Очень высокая нестабильность результатов своей реализации очереди сообщений (о возможных причинам я уже писал выше)

Использование пропускной способности памяти

В качестве бонуса приведу диаграмму пропускной способности очереди сообщений для 3-х писателей и 3-х читателей:

Пропускная способность при передачи сообщений различными API

Все тесты были проведены 5 раз, а в таблице находятся усреднённые данные

P.S. Скорость очистки памяти на тестируемом компьютере порядка 15-16ГБ/с. Все значения сверх этой цифры свидетельствуют о том, что обмен идёт через L3-кеш процессора.

Добавить комментарий