- Posted in: Development
[lang_en]
Aftrer my previous post about high-performance RoR deployment methods, I’ve got lots of messages/emails/IM conversations about some errors in previous benchmarks and there were lots of suggestions about extending of tested software set and modifying testing methodology. So, that is why I decided to perform deep and wide performance testing for all deployment schemes I can find. In this article you can find description of testing methodology and, of course, benchmarks results. If you want to know details of specific software setup, take a look at articles in category “Ruby On Rails” to find all articles from “Looking for optimal Solution” series (I’ll post all of them in next few days).
[/lang_en]
[lang_ru]
После выхода моей предыдущей статьи о методах высокопроизводительной настройки проектов на RoR, я получил море сообщений/писем и поговорил с кучей народу через IM и многие сообщения касались логических или методических ошибок в процессе тестирования или содержали в себе просьбу расширить или изменить параметры тестирования. Именно поэтому я решил провести новое тестирование – более глубокое и намного более широкое в плане охвата различных решений. В этой статье Вы сможете ознакомиться с методикой тестирования и, конечно же, с результатами проведенных тестов. Если Вас интересуют детали настройки ПО в отдельных тестах, Вы можете заглянуть в раздел сайта, посвещенный “Ruby On Rails” и прочесть отдельные сообщения из серии “В поисках оптимального решения” о каждом из тестировавшихся подходов к запуску rails-приложений (статьи о конфигурации будут готовы в течение ближайших нескольких дней).
[/lang_ru]
[lang_en]
Truly speaking, when I’ve started all these testing stuff, my main aim was to find most optimal solution for our project, but later, thanks to Dmytro Shteflyuk, I decided to perform testing with optimized software settings, to find maximum theoretical speed, that I can expect from RoR on my servers. So, you can interpret results of testing from two different points of view: as simple performance comparison of different solutions, or as highest performance marks that specific solutions can provide you (of course, you can get more by creating some more complicated schemes like “nginx/lighttpd for static content + rails for dymanic”, but this benchmark was done only for dynamic content without any caching).
First of all I want to describe hardware/software plaftorm where all performance benchmarks were done. Our development server has following configuration:
- CPU: 4 x XEON CPUs
- Memory: 4 Gb of RAM
- OS: Debian GNU/Linux Testing with recent 2.6 kernel.
- Ruby: ruby 1.8.4 (2005-12-24) [i486-linux] from Debian Testing repository.
- Rails: Rails 1.1.6 installed by gem.
All tests were performed on simple RoR appliaction with simple single-action controller:
class TestController < ApplicationController def hw @hello = "Hello, world!" @time = Time.now() end end
and simple view:
<h1>Test#hw</h1> <p>Hello: <%= @hello %></p> <p>Time: <%= @time %></p>
Rails Framwork was started with default settings in production mode. Tests were performed by ab (Apache Benchmark) utility with following params:
$ ab -c 100 -n 10000 http://SERVERIP:PORT/test/hw
where PORT is specific port number that has was chosen for every test.
I decided to not use any DB-related code because I want to get top performance marks for Ruby On Rails engine, not for some mysql/postgres/oracle/etc software. Simple code, simple tests, simple and understandable results.
Notice: Before each tests all files from tmp/sessions were deleted because with lots of test requests to server I’ve got very poor results for some software because of file-system layer lags. So, if you’ll decide to check my tests on your own hardware/software, clean sessions dir after every test run.
While tests were running I’ve monitored server with top/iostat/vmstat to understand test results better… and that is why all fastcgi/proxy/lsapi tests were done with 4 backend processes – server has 4 CPUs and 4 processes performed better than 2/5/8/10.
So, let me describe tested configurations shortly before I will show you benchmark results (links will be pointed to detailed description of tests later).
- WEBrick/1.3.1 – I’ve tested it only to get some base performance value to compare with all other test results.
- mongrel (single process) – This test was performed to get information about what performance gain we can get if will user single mongrel server without any balancing software.
- lighttpd (4 mongrels) – Test of lighttpd load-balancing between several tcp backend servers.
- lighttpd (4 fastcgi processes) – Test of lighttpd load-balancing between several fastcgi backend servers.
- nginx (4 mongrels) – Test of nginx load-balancing between several tcp backend servers.
- nginx (4 fastcgi processes) – Test of nginx load-balancing between several fastcgi backend servers.
- pen (4 mongrels) – Test of pen load-balancing between several tcp backend servers.
- pound (4 mongrels) – Test of pound load-balancing between several tcp backend servers.
- haproxy (4 mongrels) – Test of haproxy load-balancing between several tcp backend servers.
- apache 2.0 (4 fastcgi processes) – Test of apache 2.0 load-balancing between several fastcgi backend servers.
- LiteSpeed (4 lsapi instances) – This really exotic software I tested because someone asked me about this test in comments for previous benchmark. LiteSpeed web-server have some SAPI module for ruby that, AFAIU, works like FastCGI, but with some improvements. But unfortunately, optimized version of this server costs some money and not all can use it for their projects (it has some free version, but if you want server, optimized for performance, you should pay lots of money).
Now, when you know about all of my tests, I can show you information about tests results. First of all, if you want to see results in table view, here is screenshot from my Excel spreadsheet:
If you like to analyze results in graphical presentation, you can take a look at the following diagram, that shows QPS (queries per second) results for all tests:
Speaking about these results, I can say, that all of them were predictable – TCP is really slower that unix sockets, that were used in fastcgi tests. So all tests with tcp-based backend commmunications have less QPS, than unix socket based. But you should understand, that tcp-based frontend-backend communication provides you with greay scalability mechanism and you can move backend instances between servers without any problems. So, if you need absolutely best performance on one server, I would recommend you to use nginx with fastcgi backend processes. But if you need better scalability, you can use nginx with mongrel-servers as backend processes.
[/lang_en]
[lang_ru]
Честно говоря, когда я начинал все это тестирование, моей основной целью был поиск наиболее оптимального решения для инсталляции моего проекта. Но позже, блягодаря критике Дмитрия Штефлюка, я решил проводить тестирование, стараясь выжать максимум из каждого теста с целью найти максимальную теоретическую скорость, которую я могу ожижать от моих серверов при работе с Ruby on Rails. Поэтому Вы можете интерпретировать результаты тестирования с двух различных точек зрения: как простое сравнение производительности различных решений или как оценку сверху возможной производительности вашего решения (конечно, вы можете получить больше от этих решений если будете использовать более сложные схемы вроде “nginx/lighttpd для статики + rails для динамики”, но это тетсирование проводилось только для динамики без использование различных схем кеширования).
В первую очередь хотелось бы описать платформу, на которой производилось тестирование. Наш development-сервер имеет следующую аппаратно-программную конфигурацию:
- CPU: 4 x XEON CPUs
- Память: 4 Gb of RAM
- OS: Debian GNU/Linux Testing с последним 2.6 ядром.
- Ruby: ruby 1.8.4 (2005-12-24) [i486-linux] из репозитория Debian Testing.
- Rails: Rails 1.1.6 проинсталлирован из gem.
Все тесты проводились на простом rails-приложениис одним single-action контроллером:
class TestController < ApplicationController def hw @hello = "Hello, world!" @time = Time.now() end end
м простым view:
<h1>Test#hw</h1> <p>Hello: <%= @hello %></p> <p>Time: <%= @time %></p>
Rails Framework был запущен с настройками по-умолчанию для production mode. Тесты были выполнены при помощи программы ab (Apache Benchmark) со следующими параметрами:
$ ab -c 100 -n 10000 http://SERVERIP:PORT/test/hw
где PORT – это специфичный для каждого теста номер порта, на котором принимаются запросы.
Я решил не добавлять никакого I DB-related кода, т.к. моей целью было тестирование проиводительности движка Ruby On Rails, а не mysql/postgres/oracle/etc. Простой код, простые тесты, простые и понятные результаты.
Замечение: Перед каждым тестом все файлы из каталога tmp/sessions удалялись, т.к. после огромного количества запросов там скапливается очень много файлов и на результаты теста начинают влиять проблемы файловых систем. Потому, если вы захотите повторить проделанные мною тесты на своей платформе, очищайте этот каталог перед каждым тестом.
В процессе работы тестов я наблюдал за сервером при помощи top/iostat/vmstat с целью понять, почему результаты получились именно такими… и именно поэтому во всех тестах с учатием fastcgi/proxy/lsapi использовались 4 backend-процесса – у сервера 4 CPU и 4 процесса показали себя наиболее производительно по сравнению с 2/5/8/10.
Итак, позвольте мне кратно описать протестированные конфигурации перед тем, как показать вам результаты тестирования (ссылки с названий тестов позже будут вести на более детальные описания конфигураций).
- WEBrick/1.3.1 – Был протестирован с единственной целью – получить некоторую величину, с которой можно будет сравнивать все остальные результаты тестов.
- mongrel (single process) – Этот тест был проведен для того, чтобы получить информацию, насколько сильно меняет производительность использование одного процесса mongrel без балансирующего ПО.
- lighttpd (4 mongrels) – Тест на качество реализации в lighttpd балансировки нагрузки между несколькими tcp backend серверами.
- lighttpd (4 fastcgi processes) – Тест на качество реализации в lighttpd балансировки нагрузки между несколькими fastcgi серверами.
- nginx (4 mongrels) – Тест на качество реализации в nginx балансировки нагрузки между несколькими tcp backend серверами.
- nginx (4 fastcgi processes) – Тест на качество реализации в nginx балансировки нагрузки между несколькими fastcgi серверами.
- pen (4 mongrels) – Тест на качество реализации в pen балансировки нагрузки между несколькими tcp backend серверами.
- pound (4 mongrels) – Тест на качество реализации в pound балансировки нагрузки между несколькими tcp backend серверами.
- haproxy (4 mongrels) – Тест на качество реализации в haproxy балансировки нагрузки между несколькими tcp backend серверами.
- apache 2.0 (4 fastcgi processes) – Тест на качество реализации в apache 2.0 балансировки нагрузки между несколькими fastcgi серверами.
- LiteSpeed (4 lsapi instances) – Этот экзотический продукт был проверен только из-за того, что в коментариях к прошлому тестированию я увидет просьбу проверить его. Веб-сервер LiteSpeed содержит в себе какой-то SAPI модуль для ruby который, AFAIU, работает как обычный FastCGI, но с некоторыми улучшениями в плане производительности. Но, к несчастью, оптимизированная версия стоит некоторого количества денег, что значительно ограничивает круг ее пользователей (у них есть бесплатная версия, но если вам нужна от сервера производительность, но придется заплатить достаточно много денег).
Ну, вот и настало время представления результатов тестирования. Прежде всего хочу представить результаты в табличном виде (screenshot из Excel-таблицы:
Если Вам приятнее анализировать результаты в графическом представлении, Вы можете взглянуть на следующую диаграмму, показывающую QPS (количество запросов в секунду) для всех тестов:
Говоря о результатах, Я могу скзаать, что все они были предсказуемы – TCP действительно медленнее, чем unix sockets, которые использовались в тестах с fastcgi. Поэтому все тесты, в которых общение с backend-сервером происходит через tcp, имеют QPS ниже, чем основанные на unix socket. Но должен обратить Ваше внимание на следующий факт: общение frontend-backend через tcp тоже дает отличную производительность сохраняя при этом практически не ограниченную масштабируемость решения и возможность переносить backend-сервера между физическими машинами без каких-либо проблем. Итак, если вам нуобходима абсолютно максимальная производительность от одного сервера, я бы порекомендовал использовать nginx с fastcgi backend-процессами. Но если вам необходима масштабируемость, вы можете использовать nginx с mongrel-серверами в качестве backend-процессов.
[/lang_ru]