Схватка Elixir и Ruby. Phoenix против Rails
Эта статья — демонстрация сравнительного анализа языков Elixir и Ruby: в ней пойдёт речь о том, какую производительность обеспечивают веб-фреймворки Phoenix и Rails при выполнении одних и тех же задач. Прежде чем перейти к примерам кода и результатам бенчмарков, ответим на несколько распространённых вопросов о тестах такого рода.
Если коротко, то Phoenix справился с заданием в 10,63 раза быстрее, чем Rails, обеспечив более низкую загрузку CPU.
ЧАВО
Не думаете ли вы, что пытаетесь сравнить несравнимое?
Вовсе нет. Приведённые тесты — прямое сопоставление полюбившихся особенностей Ruby (Rails) с Elixir (Phoenix). Elixir гарантирует предоставить то, что все так ценят в Ruby: скорость разработки, метапрограммирование, изящные API и DSL, но при этом работать быстрее, обеспечивая надёжную конкурентную модель и распределённую обработку данных. Цель данной статьи — выяснить, как уже полюбившиеся особенности Ruby без потери удобства программных интерфейсов реализуются в Elixir с точки зрения производительности веб-фреймворков.
Так ли необходимы бенчмарки?
Бенчмарки — не что иное, как средство заблаговременного обеспечения надёжности работы тестируемых программ. Но даже в этом случае бенчмарки всего лишь позволяют получить представление о каких-либо характеристиках. Поэтому мораль здесь такова: не стоит полагаться на бенчмарки, нужно всегда проводить проверки вручную.
Что конкретно вы сравниваете?
Elixir Phoenix Framework
- Phoenix 0.3.1
- Cowboy webserver (single Elixir node)
- Erlang 17.1
- Ruby on Rails
Rails 4.0.4
- Rails 4.0.4
- Puma webserver (4 воркера — по одному на каждое ядро)
- MRI Ruby 2.1.0
Мы проводим сравнение быстродействия двух эквивалентных приложений на Phoenix и на Rails, причём для большей наглядности определённые задачи рассматриваются отдельно. Для оценки выполним следующие пункты.
-
Сопоставим запрос к серверу и направим его к соответствующему действию контроллера, разбирая именованные параметры
-
Внутри контроллера рендерим представление (в зависимости от заголовка Accept в запросе), которое помещается в родительский макет. Представления рендерятся посредством встроенных в язык шаблонизаторов (ERB, EEx).
-
В представлении рендерим коллекцию данных, полученных из контроллера.
-
Отправляем ответ клиенту.
Вот и всё. Мы тестируем типовое сопоставление маршрутов и отображение стека представлений, что явно выходит за рамки примера «Hello World». В обоих приложениях производится рендеринг макета, представлений и их составляющих для проведения анализа реальной производительности при выполнении основной задачи веб-фреймворка. Чтобы не перегружать IO в обоих приложениях отключены кэширование представлений и логирование запросов. Для проведения бенчмаркинга мы использовали
Маршрутизаторы
Phoenix
Rails
Контроллеры
Phoenix
Rails
Представления
Phoenix (EEx)
Rails (ERB)
Результаты для локального сервера
Phoenix показал в 10,63 раза большую производительность и более устойчивое среднеквадратическое отклонение времени задержки. Такие результаты доказывают реальные преимущества конкурентной модели Elixir. Одна нода Elixir использует все необходимые ресурсы CPU и требуемый объём памяти, в то время как веб-сервер Puma (Rails) для реализации многопоточности создаёт по одному процессу на каждом ядре CPU.
Phoenix
Rails
Результаты для Heroku (1 dyno)
Phoenix оказался в 8,94 раза производительнее, снова показав намного более устойчивое среднеквадратическое отклонение времени задержки и в 3,74 раза меньшую загрузку CPU. Пытаясь получить на сервере Phoenix такую же нагрузку на CPU, как и на сервере Rails, мы столкнулись с нехваткой доступных сокетов. Возможно, Phoenix-приложение показало бы большую производительность, если бы сети клиентов имели более высокую пропускную способность. В случае использования удалённого сервера значение среднеквадратического отклонения имеет особую важность. Rails-приложение не смогло обеспечить устойчивое время отклика, показав результат времени задержки более 8 секунд. На практике, Phoenix-приложение в нагруженном состоянии должно работать намного более стабильно, чем приложение на Rails.
Phoenix (Cold)
Phoenix (Warm)
Загрузка
Rails (Cold)
Rails (Warm)
Загрузка
Обобщённые результаты
Elixir сочетает в себе удобство и скорость разработки Ruby с конкурентной моделью и отказоустойчивостью Erlang. Программируя на Elixir, можно одновременно пользоваться преимуществами двух этих языков, в связи с чем я призываю вас ознакомиться с Phoenix. Придётся ещё попотеть над доработкой Phoenix, чтобы он мог сравняться с мощной экосистемой Rails, но это только начало. На этот год у нас уже большие планы.
Если вы хотели бы собственноручно провести такое же тестирование, то созданные приложения находятся в свободном доступе
За предоставленную информацию об установке приложений Heroku и тестировании удалённых серверов благодарим