SObjectizer v.4.4 beta5 Notes

Author: Евгений Охотников
Contact: eao197 at intervale dot ru; eao197 at yahoo dot com
Date: 2007.11.01

Contents

Введение

Это небольшой рассказ об основных изменениях в SObjectizer v.4.4.b5 по сравнению с предыдущими публичными бета-версиями (в основном, от третьей беты). И о том, почему между двумя публичными релизами прошло так много времени -- целый год.

Во время работы над so-4.4.0-b3 стало понятно, что необходимо кардинально менять транспортную подсистему SObjectizer. Именно этому было уделено основное внимание во время разработки очередной, четвертой, бета версии. В конце-концов четвертая бета была завершена и практически сразу же использована в ряде эксплутирующихся в компании Интервэйл программных системах. Но в ней коммуникационные SOP-каналы не поддерживали zip-ования SOP-трафика, что вскоре негативно сказалось в некоторых типах приложений. Поэтому четвертая бета не была опубликована, т.к. основные усилия были направлены на разработку очередной, пятой беты, в которой zip-ование SOP-трафика уже поддерживалось.

В результате в so-4.4.0-b5 полностью переделана транспортная подсистема и, тем самым, нарушена совместимость с предшествующими версиями на уровне исходных текстов. К счастью, это оказалось не так страшно, поскольку:

Повышение производительности Run-Time

В so-4.4.0-b5 удалось немного повысить производительность SObjectizer Run-Time за счет выполнения некоторых операций подсчета ссылок для агентов/сообщений с помощью атомарных операций (вместо mutex-ов в предыдущих версиях).

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

Еще чуть-чуть производительности удалось выжать за счет использования собственных аллокаторов (использовался dlmalloc) для классов so_4::rt::event_data_t и so_4::rt::impl::event_data_single_t.

Повышение эффективности транспортной подсистемы

Предшествующие версии SObjectizer использовали самописные средства работы с IPC-механизмами, т.е. с TCP/IP сокетами. Переход версии 4.4.0 на ACE позволил использовать ACE_Reactor и ACE_Acceptor/ACE_Connector, что самым благоприятным образом сказалось на производительности транспортной подсистемы.

Тесты-benchmark-и

Ниже описываются некоторые benchmark-тесты, которые использовались для тестирования so-4.4.0-b5 и приводятся результаты замеров скорости передачи данных. Тестирование выполнялось на ноутбуке с процессором Intel Core2 Duo 2GHz, 2Gb оперативной памяти, Windows-XP SP2. Программы компилировались с помощью Visual C++ 7.1 с установленным SP1. Все программы запускались локально, на одном компьютере.

Все описанные ниже тесты входят в дистрибутив so-4.4.0-b5, они располагаются в каталоге test/bench и компилируются автоматически при выдаче команды:

ruby test/build_tests.rb --mxx-cpp-release

Тест tcp_echo_client_server

В этом тест есть процесс-сервер, открывающий серверный TCP/IP сокет, и процесс-клиент, подключающийся к процессу-серверу. Оба процесса используют RAW-каналы.

Клиент отсылает серверу пакет длинной N байт. Сервер отвечает клиенту теми же самыми данными. Получив от сервера весь пакет, клиент отсылает серверу следующий пакет. И т.д. Клиент отсылает серверу M пакетов. Размер пакета и количество пакетов задаются в командной строке.

Данный тест показывает, насколько эффективно транспортная система SObjectizer с использованием ACE_Reactor способна определять появление очередной порции входящих данных. И насколько быстро уходят в коммуникационный канал одиночные исходящие пакеты.

При размере пакета в 256 байт и количестве пакетов >= 10K достигается пропускная способность в 10500 пакетов в секунду.

Тест server_client_speed

Тест, аналогичный предыдущему, но используются SOP-каналы и клиент посылает серверу не один запрос за раз, а группу из K запросов. Размер сообщения, количество сообщений и размер одной группы задаются в командной строке. Так же в командной строке можно включать и выключать zip-пование SOP-каналов.

Если zip-ование отключено, то при размере сообщения в 256 байт и количестве пакетов >= 50K получаются следующие результаты:

  • при одном сообщении в группе пропускная способность достигает 4800 сообщений в секунду;
  • при десяти сообщении в группе пропускная способность достигает 8200 сообщений в секунду;
  • при ста сообщениях в группе -- 9300 сообщений в секунду;
  • при тысяче сообщений группе -- 10200 сообщений в секунду.

Если zip-ование включено, то при тех же самых условиях получаются следующие результаты:

  • при одном сообщении в группе -- 2700 сообщений в секунду.
  • при десяти сообщениях в группе -- 4500 сообщений в секунду.
  • при ста сообщениях в группе -- 4800 сообщений в секунду.
  • при тысяче сообщений в группе -- 5000 сообщений в секунду.

Cоображения о производительности транспортной подсистемы

Производительность RAW-каналов в SObjectizer во многом определяется накладными расходами ACE_Reactor и операционной системы на такие операции, как переключение контекстов нитей и определение готовности сокетов к чтению/записи.

Если сравнивать производительность RAW-каналов SObjectizer с простейшей реализацией echo-сервера, где сервер постоянно висит на чтении, а клиент либо постоянно пишет в сокет, либо постоянно читает, то SObjectizer в 2-2.5 раза медленнее (у меня подобный примитивный тест показывает порядка 28000 сообщений в секунду). Однако, если сделать тест, который использует ACE_Reactor и выполняет операции ввода-вывода исключительно в методах ACE_Event_Handler::handle_input/handle_output (т.е. когда ACE_Reactor диагностирует готовность сокета к чтению/записи), то SObjectizer в 2 раза быстрее (у меня такой наивный ACE_Reactor-тест показывает порядка 4500-5000 сообщений в секунду).

Проблемой SObjectizer-а здесь является достаточно долгий путь, который RAW данные проходят от агента-отправителя (который не контролирует сокет) до самого сокета. Ведь сообщения должны сначала попасть к транспортному агенту и только от него они уйдут в сокет. Да и то не сразу. Аналогичный путь проделывают и входящие данные -- данные из сокета вычитываются на какой-то нити ACE_Reactor-а, оформляются в сообщение транспортного агента, а обрабатываются уже на какой-то нити SObjectizer-а в подписавшемся на них агенте. Переключение контекста нитей здесь сказывается отрицательно и существенно, но этого переключения нет в примитивных тестах, показывающих самую высокую производительность.

SOP-каналы страдают от длительного пути исходящих/входящих данных еще больше. Ведь исходящее сообщение глобального агента сначала поступает агенту-коммуникатору для сериализации, затем сериализованный SOP-пакет приходит транспортному агенту и только затем в сокет. Входящий SOP-пакет идет сначала агенту-коммуникатору для десериализации и только после этого входящее сообщение глобального агента приходит к своему получателю. Поэтому при обмене одиночными сообщениями SOP-каналы в SObjectizer оказываются в два раза медленнее RAW-каналов.

Проведенные модификации

Средства для подсчета ссылок

В so-4.4.0-b5 используется специальный класс increment_decrement_host_t из пространства имен so_4::rt::impl::ref_count_ops, который использует средства ACE для выполнения операций инкремента/декремента счетчика ссылок через атомарные операции. Если же на данной платформе атомарные операции не поддерживаются (нет символа ACE_HAS_BUILTIN_ATOMIC_OP), то класс increment_decrement_host_t работает с помощью mutex-ов.

Транспортная подсистема

Все старое выброшено (понятие io_channels, старые классы транспортных агентов). Добавлено пространство имен so_4::transport_layer, в котором инкапсулируются низкоуровневые детали работы с IPC-механизмами. Добавлены новые классы транспортных агентов (a_raw_outgoing_channel_t, a_raw_incoming_channel_processor_t, a_sop_outgoing_channel_t a_sop_incoming_channel_processor_t), которые используют общую, достаточно простую, кодовую базу.

Для транспортных агентов добавлена возможность более гибкого управления параметрами коммуникационных каналов (например, размеры буферов ожидающих исходящих данных, размеры блоков при операциях ввода-вывода, включение/выключение zip-ования SOP-каналов и пр.).

Одним словом, SObjectizer получил совершенно новую транспортную подсистему. Хотя и оставил основные принципы взаимодействия прикладных и транспортных агентов.

Направления дальнейшего развития

Пятая бета SObjectizer стала последним шагом, завершившим окончательный переход SObjectizer на средства библиотеки ACE. Поэтому грядущие изменения в SObjectizer будут направлены на расширенное использование средств ACE, т.е. будет осуществляться переход от революции к эволюции.

В следующих бетах SObjectizer хотелось бы уделить внимание двум основным направлениям:

Так же есть подозрение, что в SObjectizer можно устранить еще несколько узких мест. Например, можно попробовать отказаться от сериализации/десериализации сообщений глобальных агентов в агенте-коммуникаторе. И сократить накладные расходы на диспетчеризацию заявок на выполнение событий агентов за счет сохранения в каждом агенте информации о контексте, на котором агент запускает свои события.

Так что работы еще много, хотя уже можно более-менее четко обозначать грани финальной версии 4.4.0.

Почему потребовался целый год?

Между публикациями so-4.4.0-b3 и so-4.4.0-b5 прошел год. Это слишком большой срок. И объясняется он простым правилом номер 10:

Вполнакала проекты не делаются. (Правила Ашманова, часть 2)

Разработка SObjectizer является лишь частью моей работы. Временами очень небольшой частью. А переделка транспортной подсистемы оказалась слишком сложной для меня задачей, чтобы выделять время на ее решение по остаточному принципу. За прошедший год было предпринято несколько попыток спроектировать новые транспортные агенты на основе ACE_Reactor, но почти все они завершились ничем. Более-менее успешной оказалась только последняя попытка, да и то после первых реальных замеров производительности вскрылось несколько неприятных просчетов, из-за чего потребовалась весьма серьезная переработка первоначального проектного решения.

Так случилось, что в это время в наиболее важном из моих проектов, построенных на основе SObjectizer, критически важной стала поддержка быстрого синхронного (т.е. в режиме запрос-ответ) взаимодействия двух удаленных приложений. Такое стечение обстоятельств позволило мне отложить всю повседневную рутину и с головой окунуться в развитие SObjectizer. Т.е. удалось заработать в полный накал :)

Хотелось бы верить, что дальнейшая работа над SObjectizer пойдет быстрее. Все-таки революций больше не предвидится, теперь можно просто расширять функциональность SObjectizer-а. Однако, загадывать что-либо уже страшновато. Тем более, что своей публикации ждут еще несколько построенных над SObjectizer библиотек (gemont - для мониторинга приложений, so_log - для поддержки логирования, mbapi - еще более высокоуровневый обмен сообщениями), что отнимет изрядное количество сил и времени на подготовку к их публикации.

Так что, поживем -- увидим. Главное, что после завершения so-4.4.0-b5 желание продолжать дальнейшее развитие SObjectizer не исчезло, а наоборот -- усилилось!

Благодарности

В заключение хочу еще раз высказать благодарность всем, кто проявил внимание к SObjectizer, кто скачивал его, кто задавал вопросы, высказывал свои предложения и замечания. Ваш интерес являлся большим стимулом и не позволял опускать руки после очередных неудач.

Отдельное спасибо руководству компании Интервэйл и лично Андрею Лабычу за возможность продолжать этот интересный проект.

Громадная благодарность нашей службе техподдержки и лично Владиславу Волкову за терпение и помощь в совершенствовании наших технологий, в том числе и SObjectizer.

И, конечно же, самое большое спасибо всем нашими разработчиками, которые ежедневно используют SObjectizer -- за то, что я пока не попадался им в темном переулке :)

Дополнительная информация

Новая транспортная подсистема

Принцип работы коммуникационных каналов

Hosted by uCoz