вторник, 6 января 2009 г.

SObjectizer vs Kilim

Некто Sujit Pal в своем блоге привел результаты сравнения производительности нескольких агентных фреймворков для Java (сравнивались Kilim, Jetlang, Actor Guild, ActorFoundry, а так же Scala Actors из стандартной библиотеки языка Scala). Двумя наиболее быстрыми фреймворками оказались Kilim и Jetlang. Поскольку в блоге были опубликованы исходные тексты тестового приложения для Kilim, то я сравнил скорость работы SObjectizer 4.4.0-beta6 с Kilim 0.50.

 

На моей машине (Intel Core2Duo 2GHz, 2Gb RAM, WinXP) Kilim-приложение отработало за 12.870 секунды, а SObjectizer-приложение – за 11.828 (обе цифры являются усредненными по нескольким запускам результатами). В качестве JVM использовалась клиентская Java-машина из состава Java 1.6.0_07. SObjectizer-приложение компилировалось с помощью Visual C++ 2005. В процессе работы Kilim-приложение потребляло до 170Mb памяти, а SObjectizer-приложение – до 80Mb. Вот исходный текст SObjectizer-приложения.

 

Результаты тестов меня, честно говоря, несколько расстроили. Я рассчитывал на более серьезное преимущество SObjectizer за счет использования нативного кода. Но, видимо, в данном тесте, где создается большое количество мелких объектов-строк, сборщик мусора в Java делает выделение динамической памяти гораздо более быстрым, чем в C++.

 

Тем не менее, результат не самый плохой. Особенно с учетом того, как сообщения отсылаются в Kilim и в SObjectizer. В Kilim актеры должны владеть ссылками на конкретные объекты mailbox-ы, непосредственно в которые сообщения и помещаются. Тогда как в SObjectizer при отсылке сообщения есть только строковое имя агента-владельца сообщения, по которому SObjectizer сам находит получателя сообщения. Т.е. при отсылке сообщений в SObjectizer4 выполняется больше работы, чем в Kilim. Кроме того, в SObjectizer существуют понятия состояний и событий, которых нет в Kilim. А на работу с этими сущностями в SObjectizer так же тратится время и ресурсы.

 

Отдельно хотелось бы отметить один важный, на мой взгляд, момент. В упомянутых Java/Scala фреймворках процесс выборки сообщений агентами выглядит очень примитивным. Это обычный цикл, в начале которого из mailbox-а извлекается очередной объект-сообщение, после чего в виде if-ов, switch-ей или pattern matching-а (как в Scala) определяется, что же с этим сообщением нужно делать. Лично мне такой подход не нравится, я считаю его утомительным в написании, он череват ошибками и он сложен при сопровождении чужого кода. Я в очередной раз убедился, что лучше, когда фреймворк берет на себя задачу сопоставления очередного сообщения конкретному методу объекта.

 

Проведение данного сравнения так же привело меня к следующим выводам:

 

1. Ясно видно, что модель актеров сейчас стремительно набирает популярность. Об этом свидетельствует рост внимания к языку программирования Erlang, большое количество рассуждений на тему удобства модели актеров в блогах, растущее количество агентных фреймворков для Java. И это хорошо, т.к. формируется благоприятная для SObjectizer среда.

 

2. Если в области управляемых (managed) языков вроде Java/Scala/Python/Ruby наблюдается рост разнообразных (по мнению их авторов) агентных фреймворков, то для C++ такого роста не видно вообще. Что, на мой взгляд, благоприятно для SObjectizer – C++ умирать пока не собирается, и в C++ приложениях можно получить выгоды от использования модели актеров. Поэтому имеет смысл развивать SObjectizer именно как C++ инструмент.

 

3. В SObjectizer нужно вводить механизмы обмена сообщениями, которые не требуют поиска получателя сообщения по имени. Например, что-то типа mailbox-ов, как в Kilim, или каналов (channels, pipelines). Т.е. если двум агентам нужно обмениваться сообщениями друг с другом, они создают объект-канал, ссылка на который есть у обоих. И для отсылки сообщений они используют не send_msg, а метод записи сообщения в канал. Тем более, что каналы могут применяться так же для контроля за переполнением очереди сообщений агента.

воскресенье, 4 января 2009 г.

Очередные мысли о защите агентов от перегрузки

На днях через ленту новостей получил ссылку на интересный блог-пост. Суть в том, что Erlang-приложение, которое отлично работало на 2-х ядерной машине, при переносе на 8-ми ядерную машину начало падать из-за нехватки памяти. Причина оказалась в том, что один из медленных Erlang-процессов успевал разгребать свою очередь сообщений, когда его нагружали процессы с 2-х ядер. Но как только инициаторы сообщений получили в свое распоряжение 8-мь ядер, они стали генерировать так много работы для этого медленного процессора, что его очередь заполнялась быстрее, чем он успевал ее чистить. В результате очередь сообщений сжирала всю свободную память и все приложение падало.

 

Этот пример является хорошим показателем того, насколько важно в агентной системе следить за тем, чтобы каждый агент получал не больше сообщений, чем способен обрабатывать. Т.е. важность задачи overloading control. Которая в SObjectizer4 пока не имеет штатного решения. В поисках такого решения родилась очередная идея.

 

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

 

PS. Упомянутый мной блог-пост примечателен еще одним наблюдением. Люди написали на Erlang-е некую message switching platform (чтобы под этим не понималось), производительность которой на 2-х ядрах составляет 140 транзакций в секунду. Что они считают достаточной. При переходе на 8-мь ядер они получили прирост до 700 транзакций в секунду. Что они оценивают как хорошую масштабируемость. Сложно, конечно, оценивать их производительность, не зная, что именно они делают. Но, учитывая, что при 700 т/cек. узким местом были ни БД, ни другие компоненты системы, можно сделать вывод, что 140 т/сек. – максимум, который дает именно Erlang, далеко не самый быстрый язык программирования. Т.е. если бы они взяли вместо Erlang-а что-то более производительное (в особенности C++ и SObjectizer), то изначально могли иметь показатели в районе 500-600 т/сек. Но, видимо, это хороший пример, когда скорость работы программистов гораздо важнее скорости работы создаваемой им программы. И это компенсируется более производительным железом…