результаты тестирования производительности шести ведущих веб-фреймворков
Несколько месяцев назад я выбирал фреймворк для работы. Главную роль для меня играли простота его использования, стабильность и производительность.
За неимением в Интернете конкретной развернутой информации о сравнении скорости фреймворков, (я нашел только одно достаточно голое тестирование: оно ограничивалось тремя фреймворками RubyOnRails, Django, Symfony и не содержало деталей), я провел детальный анализ для определения самого оптимального из шести ведущих по наиболее значимым параметрам.
Итак, цель тестирования - определение скорости работы самих фреймворков и сравнения их друг с другом по скорости генерирования страниц и максимальному количеству запросов на данной конфигурации.
Я выбрал тестовую модель, при которой контроллер рендерил определенный шаблон и генерировал ответ. В итоге получался HTML-файл c "Hello World!". База данных в тесте не используется, так как она сама накладывает сильные ограничения на скорость.
Я не пытался сравнить функциональность фреймворков, коммьюнити, работу с базой данных. Мне важно было определить скорость работы именно движка MVC фреймворка, по возможности уменьшив влияние внешних факторов.
Поэтому я использовал связку Nginx + FCGI.
Были протестированы следующие фреймворки:
- CodeIgniter на PHP;
- Catalyst на Perl;
- Django на Python;
- Django на Python с Psyco;
- RubyOnRails на Ruby;
- Symfony на PHP;
- TurboGears на Python.
Тестирование проводил на следующем железе и софте:
- CPU: AMD OpteronT Processor 146 (2 GHz);
- Memory: 2 GB;
- OS: Debian 3.1 (Linux 2.6.14);
- Web-Server: nginx/0.5.5.
Версии фреймворков:
- CodeIgniter 1.5.1;
- Catalyst 5.7006 Rev.5996;
- Django Rev.4254 (28Dec.2006);
- RoR 1.1.6;
- RoR 1.2.1;
- Symfony 1.0beta2 SVN-Rev 3122;
- Turbogears 1.0b3 Rev.2323.
Версии языков программировнаия:
- Python 2.4.4;
- Python Psyco 1.5.2;
- Flup Rev.2303;
- Ruby 1.8.5-p12;
- mongrel 0.3.13.4;
- PHP 5.2.0 (cgi-fcgi);
- Perl v5.8.4, CPAN ver 1.8802.
Программы для тестирования:
- Siege 2.65;
- Http_load 12.03.2006;
- ab 2.0.41-dev Rev: 1.141.
методика тестирования
1. Измерение памяти (ps aux: VSZ "virtual set size" и RSS "resident set size").
2. Тестирование ApacheBenchmark (2 раза подряд):
ab -c 5 -n 1000 http://project.com/
3. Измерение памяти и израсходованного процессорного времени (ps aux: VSZ, RSS, %CPU, %MEM).
4. Перезапуск фреймворка.
5. Тестирование ApacheBenchmark (2 раза подряд):
ab -c 100 -n 10000 http://project.com/
6. Измерение памяти и израсходованного процессорного времени.
7. Перезапуск фреймворка.
8. Измерение http_load:
http_load -rate 10 -seconds 5 project.com
9. Измерение памяти и израсходованного процессорного времени.
10. Перезапуск фреймворка.
11. Тест Siege c 50 одновременными пользователями в течение одной минуты:
siege -d1 -t1M -c50 project.com
12. Тест Siege c 200 одновременными пользователями в течение одной минуты:
siege -d1 -t1M -c200 project.com
13. Тест Siege c 300 одновременными пользователями в течение одной минуты:
siege -d1 -t1M -c300 project.com
14. Измерение памяти и израсходованного процессорного времени.
комментарии к методике
Для начала я прогнал один Nginx с простейшим конфигом, при котором на любой запрос выдается точечный прозрачный gif-файл размером 43 байта, генерируемый самим сервером.
Этим тестом была определена примерная максимальная пропускная способность самого сервера. Забегая вперед скажу, что запас его мощности в 10 раз больше пропускной способности самого быстрого фреймворка.
Все фреймворки запускались как FastCGI 127.0.0.1:PORT. Если фреймворком предусматриваются development- и production-режимы, то я работал с production.
В nginx использован одинаковый для всех конфиг.
Перезапуск фреймворка я проводил, чтобы очистить статистику между тестами разными программами.
Мои субъективные впечатления по каждому фреймворку при инсталляции и запуске.
CodeIgniter - легко ставится и быстро настраивается. Никаких проблем с ним не возникло. Для запуска использовал spawn-php.sh с пятью процессами. Довольно шустрый для PHP фреймворк.
Catalyst. Для начала надо установить CPAN и парочку модулей для FCGI. Установка выглядела несколько запутанно. Запуск также не простой. Для начала нужно запустить фреймворк:
./CatInABox/start.sh
Потом проект:
./script/world_fastcgi.pl -l 127.0.0.1:9500 -n 5
Код не так прост, но разобраться можно.
Django. Легко ставится из репозитария. Также легко создаются пректы. Запускал двумя методами prefork и threaded. Хотя питон не очень хорошо работает с тредами.
python manage.py runfcgi method=threaded host=127.0.0.1 port=8801
python manage.py runfcgi method=prefork host=127.0.0.1 port=8801
Также проверил фреймворк с модулем ускорения psyco. В manage.py вставил:
from django.core.management import execute_manager
import psyco
psyco.full()
RubyOnRails. Его было легко поставить, следуя инструкции с сайта, но оказалось сложно запустить. Хотя в интернете видел разные конфигурации для связки Nginx + FastCGI, мне не удалось запустить его вместе с nginx.
С lighttpd + FCGI же все запустилось нормально. Поэтому я воспользовался "официальной" рекомендацией запускать через сервер mongrel. Nginx+FastCGI быстрее примерно в 1.29 раз чем Nginx+Mongrel.
Запускал 5 серверов mongrel:
mongrel_rails start -d --port 8501
mongrel_rails start -d --port 8502
mongrel_rails start -d --port 8503
mongrel_rails start -d --port 8504
mongrel_rails start -d --port 8505
Через пару дней после проведения тестов вышла новая версия RoR 1.2.1
Я, конечно, проверил и ее со всеми параметрами, обновил только фреймворк. Результаты несколько шокировали: падение производительности в 2 раза на всех тестах.
Symfony. Поставить было не сложно, но зато потом намучался с самим проектом. Довольно запутанно. Для запуска использовал также spawn-php.sh с пятью процессами.
TurboGears. При установке возникли небольшие проблемы, которые, немного повозившись, все же решил. Для запуска в threaded режиме использовал рекомендованный скрипт, в котором кое что изменил.
результаты
Рис. 1. Тест ApacheBenchmark. Таблица со скоростью обработки запросов.
Примечания к рисунку 1:
*1) во второй раз фреймворк завис и не отвечал;
*2) для перевода скорости работы из mongrel в fastcgi использовался коэффициент умножения по Ковырину =1.29.
Рис. 2. Тест ApacheBenchmark. Диаграмма со скоростью обработки запросов. Тест „ab c 5 n 1000“.
Рис. 3. Тест ApacheBenchmark. Диаграмма со скоростью обработки запросов. Тест „ab c 100 n 10000“.
Примечание к рисунку 4:
*3) Питон устроен так, что при сильной нагрузке в режиме prefork он перестартует свои процессы. Поэтому невозможно определить реальную загрузку процесора и максимальное потребление памяти.
Рис. 5. Тест ApacheBenchmark. VSZ "virtual set size".
Рис. 6. Тест ApacheBenchmark. RSS "resident set size".
Рис. 7. Тест ApacheBenchmark. Загрузка процессора.
Рис. 8. Тест http_load. Таблица с результатами.
<Рис. 9. Siege тест. Общая таблица с результатами.
выводы
В общем-то результаты видны по таблицам и графикам. Позволю себе лишь некоторые дополнения.
Меньше всего потребление процессора у django. Удивил Catalyst, который при чрезмерной нагрузке резко начинает грузить процессор. Хотя потерь запросов не наблюдалось. RoR 1.2.1 под большой нагрузкой также сильно грузит процессор.
Интересно было у TurboGears, который показал низкое потребление времени CPU в тесте "ab", но зато в siege-тесте имел самый худший результат. Потребление памяти самым большим оказалось у Catalyst, у RoR оно скорее обусловлено запуском через mongrel.
PHP-фреймворки даже в спокойном состоянии занимают много ресурсов CPU.
Среднее время коннекта для всех примерна равно. Время первого отклика сильно рознится. Тут отличился Django, имея наименьшее среднее время и самое высокое максимальное время коннекта. Фреймворки на питоне показали себя с хорошей стороны, а вот Ruby разочаровал.
Во время siege-теста наблюдались потери при большом количестве "concurrent users" у CodeIgniter, Symfony, RoR 1.2.1 & 1.1.6.
Ruby быстр при небольшой нагрузке, но резко теряет производительность при большом количестве пользователей.
Psyco-модуль ускоряет Django на 15-30%, но за это приходится расплачиваться возросшим потреблением памяти VSZ на 80% в prefork-режиме и на 400% (!!!) в threaded-режиме. RSS-потребление увеличивается в 2-2.5 раза.
Prefork-режим забирает больше памяти, но за это получается система, стабильно работающая на больших загрузках, и меньшее потребление ресурсов процессора.
В threaded-режиме Django зависал под большой нагрузкой и не отвечал на запросы. Это же происходило и с TurboGears. Связано это с плохой работой питона в threaded-режиме.
распределение мест
Минимум с трехкратным превосходством над ближайшими конкурентами победил Django.
Второе и третье места поделили TurboGears и RoR 1.1.6, так как они одинаково быстры, но ведут себя по-разному при разных нагрузках, обгоняя друг друга.
Catalyst. Честно говоря, от фреймворка на перле я ожидал большего.
CodeIgniter. Фреймворки на PHP, как и ожидалось, оказались самыми медленными. Но CodeIgniter можно посоветовать тем, кто хочет программировать только на PHP и в тоже время иметь удобную и относительно быструю систему.
Результаты RoR 1.2.1 сильно шокировали: падение производительности в 2-4 раза по сравнению с 1.1.6 версией. Время первого отклика в http_load также больше в 2 раза, чрезмерно высокое потребление процессорного времени при высокой нагрузке, все это скорее говорит о какой-то ошибке в новой версии.
Symfony досталось последнее место. Очень сложный и медленный фреймворк. Разница с Django - до 35 (!!!) раз.
Alrond
За неимением в Интернете конкретной развернутой информации о сравнении скорости фреймворков, (я нашел только одно достаточно голое тестирование: оно ограничивалось тремя фреймворками RubyOnRails, Django, Symfony и не содержало деталей), я провел детальный анализ для определения самого оптимального из шести ведущих по наиболее значимым параметрам.
Итак, цель тестирования - определение скорости работы самих фреймворков и сравнения их друг с другом по скорости генерирования страниц и максимальному количеству запросов на данной конфигурации.
Я выбрал тестовую модель, при которой контроллер рендерил определенный шаблон и генерировал ответ. В итоге получался HTML-файл c "Hello World!". База данных в тесте не используется, так как она сама накладывает сильные ограничения на скорость.
Я не пытался сравнить функциональность фреймворков, коммьюнити, работу с базой данных. Мне важно было определить скорость работы именно движка MVC фреймворка, по возможности уменьшив влияние внешних факторов.
Поэтому я использовал связку Nginx + FCGI.
Были протестированы следующие фреймворки:
- CodeIgniter на PHP;
- Catalyst на Perl;
- Django на Python;
- Django на Python с Psyco;
- RubyOnRails на Ruby;
- Symfony на PHP;
- TurboGears на Python.
Тестирование проводил на следующем железе и софте:
- CPU: AMD OpteronT Processor 146 (2 GHz);
- Memory: 2 GB;
- OS: Debian 3.1 (Linux 2.6.14);
- Web-Server: nginx/0.5.5.
Версии фреймворков:
- CodeIgniter 1.5.1;
- Catalyst 5.7006 Rev.5996;
- Django Rev.4254 (28Dec.2006);
- RoR 1.1.6;
- RoR 1.2.1;
- Symfony 1.0beta2 SVN-Rev 3122;
- Turbogears 1.0b3 Rev.2323.
Версии языков программировнаия:
- Python 2.4.4;
- Python Psyco 1.5.2;
- Flup Rev.2303;
- Ruby 1.8.5-p12;
- mongrel 0.3.13.4;
- PHP 5.2.0 (cgi-fcgi);
- Perl v5.8.4, CPAN ver 1.8802.
Программы для тестирования:
- Siege 2.65;
- Http_load 12.03.2006;
- ab 2.0.41-dev Rev: 1.141.
методика тестирования
1. Измерение памяти (ps aux: VSZ "virtual set size" и RSS "resident set size").
2. Тестирование ApacheBenchmark (2 раза подряд):
ab -c 5 -n 1000 http://project.com/
3. Измерение памяти и израсходованного процессорного времени (ps aux: VSZ, RSS, %CPU, %MEM).
4. Перезапуск фреймворка.
5. Тестирование ApacheBenchmark (2 раза подряд):
ab -c 100 -n 10000 http://project.com/
6. Измерение памяти и израсходованного процессорного времени.
7. Перезапуск фреймворка.
8. Измерение http_load:
http_load -rate 10 -seconds 5 project.com
9. Измерение памяти и израсходованного процессорного времени.
10. Перезапуск фреймворка.
11. Тест Siege c 50 одновременными пользователями в течение одной минуты:
siege -d1 -t1M -c50 project.com
12. Тест Siege c 200 одновременными пользователями в течение одной минуты:
siege -d1 -t1M -c200 project.com
13. Тест Siege c 300 одновременными пользователями в течение одной минуты:
siege -d1 -t1M -c300 project.com
14. Измерение памяти и израсходованного процессорного времени.
комментарии к методике
Для начала я прогнал один Nginx с простейшим конфигом, при котором на любой запрос выдается точечный прозрачный gif-файл размером 43 байта, генерируемый самим сервером.
Этим тестом была определена примерная максимальная пропускная способность самого сервера. Забегая вперед скажу, что запас его мощности в 10 раз больше пропускной способности самого быстрого фреймворка.
Все фреймворки запускались как FastCGI 127.0.0.1:PORT. Если фреймворком предусматриваются development- и production-режимы, то я работал с production.
В nginx использован одинаковый для всех конфиг.
Перезапуск фреймворка я проводил, чтобы очистить статистику между тестами разными программами.
Мои субъективные впечатления по каждому фреймворку при инсталляции и запуске.
CodeIgniter - легко ставится и быстро настраивается. Никаких проблем с ним не возникло. Для запуска использовал spawn-php.sh с пятью процессами. Довольно шустрый для PHP фреймворк.
Catalyst. Для начала надо установить CPAN и парочку модулей для FCGI. Установка выглядела несколько запутанно. Запуск также не простой. Для начала нужно запустить фреймворк:
./CatInABox/start.sh
Потом проект:
./script/world_fastcgi.pl -l 127.0.0.1:9500 -n 5
Код не так прост, но разобраться можно.
Django. Легко ставится из репозитария. Также легко создаются пректы. Запускал двумя методами prefork и threaded. Хотя питон не очень хорошо работает с тредами.
python manage.py runfcgi method=threaded host=127.0.0.1 port=8801
python manage.py runfcgi method=prefork host=127.0.0.1 port=8801
Также проверил фреймворк с модулем ускорения psyco. В manage.py вставил:
from django.core.management import execute_manager
import psyco
psyco.full()
RubyOnRails. Его было легко поставить, следуя инструкции с сайта, но оказалось сложно запустить. Хотя в интернете видел разные конфигурации для связки Nginx + FastCGI, мне не удалось запустить его вместе с nginx.
С lighttpd + FCGI же все запустилось нормально. Поэтому я воспользовался "официальной" рекомендацией запускать через сервер mongrel. Nginx+FastCGI быстрее примерно в 1.29 раз чем Nginx+Mongrel.
Запускал 5 серверов mongrel:
mongrel_rails start -d --port 8501
mongrel_rails start -d --port 8502
mongrel_rails start -d --port 8503
mongrel_rails start -d --port 8504
mongrel_rails start -d --port 8505
Через пару дней после проведения тестов вышла новая версия RoR 1.2.1
Я, конечно, проверил и ее со всеми параметрами, обновил только фреймворк. Результаты несколько шокировали: падение производительности в 2 раза на всех тестах.
Symfony. Поставить было не сложно, но зато потом намучался с самим проектом. Довольно запутанно. Для запуска использовал также spawn-php.sh с пятью процессами.
TurboGears. При установке возникли небольшие проблемы, которые, немного повозившись, все же решил. Для запуска в threaded режиме использовал рекомендованный скрипт, в котором кое что изменил.
результаты
Рис. 1. Тест ApacheBenchmark. Таблица со скоростью обработки запросов.
Примечания к рисунку 1:
*1) во второй раз фреймворк завис и не отвечал;
*2) для перевода скорости работы из mongrel в fastcgi использовался коэффициент умножения по Ковырину =1.29.
Рис. 2. Тест ApacheBenchmark. Диаграмма со скоростью обработки запросов. Тест „ab c 5 n 1000“.
Рис. 3. Тест ApacheBenchmark. Диаграмма со скоростью обработки запросов. Тест „ab c 100 n 10000“.
Примечание к рисунку 4:
*3) Питон устроен так, что при сильной нагрузке в режиме prefork он перестартует свои процессы. Поэтому невозможно определить реальную загрузку процесора и максимальное потребление памяти.
Рис. 5. Тест ApacheBenchmark. VSZ "virtual set size".
Рис. 6. Тест ApacheBenchmark. RSS "resident set size".
Рис. 7. Тест ApacheBenchmark. Загрузка процессора.
Рис. 8. Тест http_load. Таблица с результатами.
<Рис. 9. Siege тест. Общая таблица с результатами.
выводы
В общем-то результаты видны по таблицам и графикам. Позволю себе лишь некоторые дополнения.
Меньше всего потребление процессора у django. Удивил Catalyst, который при чрезмерной нагрузке резко начинает грузить процессор. Хотя потерь запросов не наблюдалось. RoR 1.2.1 под большой нагрузкой также сильно грузит процессор.
Интересно было у TurboGears, который показал низкое потребление времени CPU в тесте "ab", но зато в siege-тесте имел самый худший результат. Потребление памяти самым большим оказалось у Catalyst, у RoR оно скорее обусловлено запуском через mongrel.
PHP-фреймворки даже в спокойном состоянии занимают много ресурсов CPU.
Среднее время коннекта для всех примерна равно. Время первого отклика сильно рознится. Тут отличился Django, имея наименьшее среднее время и самое высокое максимальное время коннекта. Фреймворки на питоне показали себя с хорошей стороны, а вот Ruby разочаровал.
Во время siege-теста наблюдались потери при большом количестве "concurrent users" у CodeIgniter, Symfony, RoR 1.2.1 & 1.1.6.
Ruby быстр при небольшой нагрузке, но резко теряет производительность при большом количестве пользователей.
Psyco-модуль ускоряет Django на 15-30%, но за это приходится расплачиваться возросшим потреблением памяти VSZ на 80% в prefork-режиме и на 400% (!!!) в threaded-режиме. RSS-потребление увеличивается в 2-2.5 раза.
Prefork-режим забирает больше памяти, но за это получается система, стабильно работающая на больших загрузках, и меньшее потребление ресурсов процессора.
В threaded-режиме Django зависал под большой нагрузкой и не отвечал на запросы. Это же происходило и с TurboGears. Связано это с плохой работой питона в threaded-режиме.
распределение мест
Минимум с трехкратным превосходством над ближайшими конкурентами победил Django.
Второе и третье места поделили TurboGears и RoR 1.1.6, так как они одинаково быстры, но ведут себя по-разному при разных нагрузках, обгоняя друг друга.
Catalyst. Честно говоря, от фреймворка на перле я ожидал большего.
CodeIgniter. Фреймворки на PHP, как и ожидалось, оказались самыми медленными. Но CodeIgniter можно посоветовать тем, кто хочет программировать только на PHP и в тоже время иметь удобную и относительно быструю систему.
Результаты RoR 1.2.1 сильно шокировали: падение производительности в 2-4 раза по сравнению с 1.1.6 версией. Время первого отклика в http_load также больше в 2 раза, чрезмерно высокое потребление процессорного времени при высокой нагрузке, все это скорее говорит о какой-то ошибке в новой версии.
Symfony досталось последнее место. Очень сложный и медленный фреймворк. Разница с Django - до 35 (!!!) раз.
Alrond
Сетевые решения. Статья была опубликована в номере 02 за 2007 год в рубрике лабораторная работа