[Из песочницы] Немного тестов производительности сетевых фреймворков

Привет Хабр! Пару месяцев назад я захотел провести тестирование производительности некоторых сетевых фреймворков, c целью понять насколько большая разбежка между ними. Надо ли использовать Node.js там, где хотелось бы Python с Gevent или нужен Ruby с его EventMachine.Я хочу обратить ваше внимание на то, что эти материалы не являются руководством к выбору фреймворка и могут содержать спорные моменты. Я вообще не собирался публиковать результаты этого исследования, но когда они попадались мне на глаза я ловил себя на мысли, что это может быть кому-нибудь полезно. На этот пост я выделил не больше 4-ех часов, иначе он не появился бы, поэтому от орфографических ошибок, как и от любых других, я не застрахован. Теперь, когда вы ко всему готовы, я начну забрасывать вас графиками.

1. Text / Httperf / VPS 1 CPU, 512 RAMПервый тест я провёл на самом дешёвом VPS DigitalOcean (1 Core, 512 SSD, 20Gb SSD). Для тестирование производительности использовалась утилита httperf. Что бы произвести необходимую нагрузку были задействованы VPS такой же конфигурации, в количестве 5 штук. Для одновременного запуска теста на всех клиентах я использовал утилиту autobench со следующими параметрами: autobench_admin --single_host --host1 example.com --port1 8080 --uri1 / --low_rate 50 --high_rate 600 --rate_step 10 --num_call 10 --num_conn 6000 --timeout 5 --clients XX.XX.XX.XX:4600, XX.XX.XX.XX:4600, XX.XX.XX.XX:4600, XX.XX.XX.XX:4600, XX.XX.XX.XX:4600 --file bench.tsv

Это тест начинает выполнение с 50 соединений в секунду (10 запросов через одно соединение) и с шагом в 10 соединений в секунду достигает 600. Каждый тест устанавливает всего 6000 соединений и все запросы, которые не были обработаны в течении 5 секунд, считаются ошибкой.

Все HTTP серверы делают одно и то же, а именно возвращают строку «I am a stupid HTTP server!» на каждый запрос. Результаты получились следующими (по оси Х — количество запросов в секунду):

Нагрузка на процессор 728e61f601ac2378d78d37debfaeb098.pngПотребление оперативной памяти (в % от 512Mb) 035b5b7921c4af2e46af23cea5c834de.pngКоличество ответов 7fb948c0c586749b21be6ba77c753b5b.pngВремя ответа (в миллисекундах) 11b1803fe79a633eaa5f8036b66afb5c.pngКоличество ошибок 711f71240309979c754a8d40fb009912.pngКак только мы достигаем 100% использования CPU, потребление оперативной памяти начинает расти, количество ответов падает, время ответа на каждый запрос растёт и начинают появляться ошибки. Как я писал выше, каждый запрос, который не получил ответ в течении 5 секунд, считается ошибкой и здесь именно это и происходит, это можно проследить на графике «Время ответа».

Результаты (в скобках количество обработанных запросов без ошибок):

Gevent (4700) Express.js (3600) Eventlet (3200) Tornado (2200) Я никогда не бываю доволен своей работой полностью, поэтому уже через пару часов я решил, что тестировать производительность на VPS не самый лучший выбор. Между фреймворками разница в производительности понятна и какие-то выводы сделать можно, но узнать сколько клиентов мы в состоянии обслужить на одном ядре настоящего процессора мы не можем. Одно дело делить с кем-то неизвестные ресурсы и совсем другое когда все ресурсы известны и в нашем распоряжении.

2. Text / Httperf / Intel® Core™ i7–4770 Quad-Core Haswell, 32 GB DDR3 RAM Для следующего теста я арендовал выделенный сервер у Hetzner (EX40) с процессором «Intel® Core™ i7–4770 Quad-Core Haswell» и 32 GB DDR3 RAM.На этот раз я создал 10 VPS, которые будут создавать необходимую нагрузку и запустил autobench со следующими параметрами:

autobench_admin --single_host --host1 example.com --port1 8080 --uri1 / --low_rate 50 --high_rate 1500 --rate_step 50 --num_call 10 --num_conn 15000 --timeout 5 --clients XX.XX.XX.XX:4600, XX.XX.XX.XX:4600, XX.XX.XX.XX:4600, XX.XX.XX.XX:4600, XX.XX.XX.XX:4600 … --file bench.tsv

Это тест начинает выполнение с 50 соединений в секунду (10 запросов через одно соединение) и с шагом в 50 соединений в секунду достигает 1500. Каждый тест устанавливает всего 15000 соединений и все запросы, которые не были обработаны в течении 5 секунд, считаются ошибкой.

Исходный код серверов тот же, что и в первом тесте. Запущена одна копия сервера, которая использует только 1 ядро. В этот тест я добавил фреймворки Twisted 13.2 и Eventmachine 1.0.3. Потребление памяти я удалил из результатов теста потому что разница, по современным меркам, ничтожна. Не буду тянуть кота за хвост, вот результаты:

Нагрузка на процессор e87ea905d60aba281f4ea8e15df11b67.png

Количество ответов 7972f587366a73aa29474bd828d61ca4.png

Время ответа (в миллисекундах) c5ad2f18fe9d984e5f210a01910e8329.png

Количество ошибок 4a760c6498c9950604c52e66e69bf809.png

Тут, как и прежде, упёрлись в CPU, чего и следовало ожидать. В среднем, производительность здесь выше в 3 раза, чем на VPS DigitalOcean (1 Core, 512Mb), из чего можно сделать соответствующие выводы о количестве выделенных нам ресурсов.

Результаты (в скобках количество обработанных запросов без ошибок):

Eventmachine (подробности ниже) Gevent (12500) Express.js (11500) Eventlet (9000) Twisted (7000) Tornado (6500) Eventmachine Eventmachine меня удивил своей производительностью и ушёл далеко от конкурентов, из-за чего мне пришлось увеличить нагрузку до 25000 запросов в секунду специально для него. Результат на графиках:

Нагрузка на процессор a283e7cf0e3410451dc24231927a0f72.png

Количество ответов 6378e51f877192f412fcd4b724ec52e9.png

Время ответа (в миллисекундах) b9f36d4285c72be301cfb9541e18c911.png

Количество ошибок a617a42a3bc2a4b4ec909de5e4dd8a81.png

У меня есть подозрения, что и 30 000 запросов он бы смог обработать, но мне надо было двигаться дальше, поэтому я не смог в этом убедиться. Вообще я к этому моменту уже знал, что буду использовать Python для своего проекта, так что фреймворки на других языках мне нужны были просто для сравнения.

3. Files / Siege / Intel® Core™ i7–4770 Quad-Core Haswell, 32 GB DDR3 RAM Как я писал выше, я не бываю доволен своей работой полностью, поэтому я лёг спать с чувством выполненного долга, а проснулся с мыслью «нужно больше тестов!». Отдавать строку текста на каждый запрос это конечно хорошо, но это не единственная функция веб-сервера, значит будем раздавать файлы.Для этого теста я использовал 10 VPS, что бы создать необходимую нагрузку. Экспериментальным путём я выяснил, что на 1 VPS DigitalOcean, в среднем, выделен канал 100Mbps. Сервер у меня был с каналом 1Gbps и мне надо было его полностью нагрузить. Файлами для раздачи послужили изображения с интернет-магазина в количестве 10 000 штук, разных размеров. Для создания нагрузки я использовал утилиту siege со следующими параметрами:

siege -i -f fileslist.txt -c 55 -b -t1M

В filelist.txt хранится список файлов, устанавливается 55 соединений и через них мы начинаем долбить сервер запросами в течении 1-ой минуты. Файлы при этом выбираются случайным образом из списка fileslist.txt. Опредёленно стоит учесть, что тест этот запускается на 10 машинах одновременно, а значит мы устанавливаем не 55, а 550 одновременных соединений. Более того, эту опцию я постоянно менял от 5 до 55 с шагом в 5, увеличивая тем самым нагрузку на сервер, и устанавливая от 50 до 550 одновременных соединений.

Вот что получаем (по оси Х — количество одновременных соединений):

Количество выполненных запросов 7ae0ae0156aff2f4e7bfa363bb0798d1.pngКоличество обработанных запросов в секунду 78a366a97dffa7ce64da289ce76874c9.pngНагрузка на процессор (в %) 63a67c52d04e5ed07f65c324658054fd.pngПотребление оперативной памяти (в % от 32Gb) 9b7d7fa5d040e3ad19b5df8a2ca56af7.pngНагрузка на канал связи (мегабайт в секунду) a0e68d68a45241252ccd19b9b98a2615.pngСреднее время ответа на запрос (в секундах) aff6ec3c42e37e6d2bb2c5236ec31004.pngВ этом тесте я добавил потребление оперативной памяти, а также веб-сервер nginx для сравнения. Здесь узким местом является канал связи, причём 1-ого ядра достаточно для того, что бы весь этот канал в 1Gbps загрузить.

Результаты (в скобках количество обработанных запросов без ошибок):

Nignx (100175) Eventlet (97925) Gevent (96918) Express.js (96162) Twisted (85733) Tornado (83241) 4. GridFS / Siege / Intel® Core™ i7–4770 Quad-Core Haswell, 32 GB DDR3 RAM На этом можно было завершать статью, но я хотел использовать MongoDB GridFS в своём проекте, поэтому решил посмотреть, как изменится производительность с её использованием. Данный тест аналогичен 3-ему, за исключением того, что все изображения в количестве 10 000 штук я залил в MongoDB и переписал веб-серверы так, что бы они раздавали файлы из базы. Итак, что мы получаем: Количество выполненных запросов c252fd1fecdd0fb6a0b4e923141e8114.pngКоличество обработанных запросов в секунду d45448b2d596b55db211684cb5aefe5f.pngНагрузка на процессор (в %) aee6fe7ace0424f03fefd1ca48ff31c4.pngПотребление оперативной памяти (в % от 32Gb) 3d27d11f529ac460dc9aa6edfe7b2f86.pngНагрузка на канал связи (мегабайт в секунду) 1d8233763b3ad55418987843076f55f0.pngСреднее время ответа на запрос (в секундах) 4ddfccee651929d23f19e96ba4ce6143.pngКоличество ошибок 43c868c81a86155fe6af18aa4b5a283e.pngВо время теста у Gevent были ответы с ошибками, поэтому я добавил график «Количество ошибок». В целом GridFS вполне можно использовать, но стоит учитывать, что сама база создаёт немалую нагрузку на CPU, а у меня было 7 свободных ядер в её распоряжении, когда с файловой системой все гораздо проще.

Результаты (в скобках количество обработанных запросов без ошибок):

Express.js (88714) Gevent (86182) Выводы MacBook Pro Retina действительно отрабатывает 9 часов на одном заряде. Node.js не единственный инструмент, как считают некоторые, для разработки сетевых приложений. Gevent выдаёт очень хорошую производительность. Оформление статьи занимает больше времени, чем её написание. Тестирование производительности сложный процесс, который занимает много времени. Если серьёзно, все зависит от условий, при которых будет работать ваш проект. Можно провести огромное число тестов, но когда сервис будет написан, все скорее всего будет совсем по другому. Например, при увеличении числа картинок с 10 000 до 1 000 000 узким местом уже становится производительность жёсткого диска, а не канал связи.

Материалы Если вы решите провести собственное тестирование или более подробно изучить моё, то этот список вам должен помочь.Отчёты Полные отчёты с индивидуальными графиками и цифрами можно скачать по этим ссылкам: Text / Httperf / VPS 1 CPU, 512 RAM Text / Httperf / Intel® Core™ i7–4770 Quad-Core Haswell, 32 GB DDR3 RAM Files / Siege / Intel® Core™ i7–4770 Quad-Core Haswell, 32 GB DDR3 RAM GridFS / Siege / Intel® Core™ i7–4770 Quad-Core Haswell, 32 GB DDR3 RAM Иструменты В своих тестах я использовал: Фреймворки В тестах принимали участие: Понятия не имею какой из меня писатель и будет ли полезно кому-нибудь моё исследование. Пишите, что вы об этом думаете.

Всем спасибо за внимание.

© Habrahabr.ru