[Из песочницы] Dart vs Node.js: сравниваем производительность на реализациях HTTP сервера
Всем доброго времени суток!
В этом году с выходом Flutter — фреймворка для кроссплатформенной разработки приложений наметился подъем хайпа по языку Dart. Как и любой перфекционист прокрастинирующий от скуки лентяй я задумался о сравнении производительности серверной реализации виртуальной машины Dart с ее потенциальным антагонистом в лице Node.js. Скажу сразу, что во мне теплилась надежда что Dart победит, а я обрету святой грааль дарующий мне превосходство над потенциальными конкурентами на ближайшие пару тройку пятилеток, но реальность оказалось немного иной…
Инструментарий
- Тестовая машина: Core I7, SSD, 12GB ОЗУ (любезно предоставленная моим прошлым работодателем)
- Нагрузочное тестирование: k6.io (кстати очень интересный по своей архитектуре фреймворк)
Организация кода приложений
Исходники
Тут я особо решил не заморачиваться и решил следовать рекомендациям, которые вычитывал в свое время на Хабре. В частности:
- Добавил полезную нагрузку в качестве работы по генерации рандомных данных (рандомных, чтобы исключить потенциальное кеширование результатов)
class Human {
constructor (id, name, surname, age, gender) {
this.id = id
this.name = name
this.surname = surname
this.age = age
this.gender = gender
}
}
- Как в Dart так и в Node.js использовал варианты синхронной и асинхронной обработки запроса.
- Применил варианты нативных решений и варианты решений на отраслевых фреймворках (aqueduct for dart и express for node.js)
- Так как в ходе исследования удалось получить существенное ускорение работы Dart при использовании aqueduct, который запускает изоляты на каждом ядре, то для целей уравновешивания применил модуль cluster для node.js
Методика тестирования
- запускал нагрузочные тесты с заданным числом запросов в секунду (500, 750) и ограничением на количество итераций теста (количество завершенных запросов)
- как приложение так и тестирующий фреймворк были запущены на одной машине, соответственно стоит понимать, что все результаты являются относительными и могут быть сравнимы только друг с другом
Результаты
Native Dart
500 rps
750 rps
- http_reqs: 309.10154/s
Aqueduct framework for Dart
500 rps
750 rps
Native Node.js
500 rps
750 rps
Node Express with Cluster
500 rps
750 rps
Выводы
- Конечно многое зависит от того как Вы реализовали логику приложения, я не особо уверен, что мой код является оптимальным как в случае dart так и node.js
- В частности функцию генерации массива можно было вывести в отдельный worker поток с асинхронным выводом, в моем случае это не было реализовано, поэтому здесь на самом деле не использована вся мошь асинхронщины
- Как в Dart так и в Node.js вывод можно было организовать через поток
- Поэтому здесь еще много места как для исследования производительности, так и для оптимизаций
- Dart в нативной реализации хендлеров показал эпичейский фейл, тем не менее при реализации через фреймворк показал впечатляющие результаты, согласно которым виртуальная машина Dart уже сейчас может составить конкуренцию Node.js
- На сколько я знаю, в оптимизацию работы V8 вложено колоссальное количество человеко-часов труда, я более чем уверен, что в виртуальную машину Dart вложено гораздо меньше времени. Поэтому у второй возможно есть достаточно больший потенциал для оптимизаций перед V8