bingo347
@bingo347
Бородатый программер

Benchmark сервера дает странные результаты, wtf?

Преамбула:
На старте разработки сайта, от которого ожидается высокая нагрузка. Соответственно выбор между 2 языками - Node.js и Go
Почему Node.js:
+ Разрабатываю на ней уже давно, хорошо владею
+ В проекте могут возникнуть однотипные задачи на клиенте и сервере, js сократит время на их разработку, за счет общего кода
- Один поток на процесс, параллелить сервер под нагрузку придется, притом стандартная балансировка запросов не очень подходит, нужно user-session-stiky - ибо память у процессов разная
- Даже при реализации session-stiky между процессами необходимо общение - а это издержки на сериализацию/десериализацию
Почему GO:
+ нативная многопоточность в едином процессе, следовательно общая память
+ ассинхронность на блокировке горутин, отсутствие callback/promise hell (es7 мне только снится, генераторы не оптимизированы и требуют издержек на работу либ аля co/bluebird)
- не писал еще на нем ничего серьезного, соответственно разработка будет медленнее, а так же замедлит разработку реализация конкурентной записи данных в память
- Дублирование кода для однотипных задач, тк на сервере go а на клиенте js

Амбула:
Решил потестить так ли хорош Go по сравнению с нодой, написал простейшие http сервера, возвращающие запрошеный url на обоих языках и потестил на ApacheBenchmark
Тестил на своей рабочей машине (Ubuntu x64 14.04, AMD A8 2.8GHz 4 core, 4Gb RAM, не чистая, много чего запущено постороннего + GUI)
На всех тестах ab запускался с concurency 100

1й тест - однопоточный, Go был ограничен командой runtime.GOMAXPROCS(1); в func init()
node.js - 4k rps / 25ms per request (далее mspr)
Go - 9k rps / 11mspr
Отлично Go выигрывает в производительности в 2-2.5 раза, при повторном запуске ab на работающем сервере оба незначительно улучшили показатели

2й тест - 4 потока, Node был распаралелен стандартным модулем cluster и реально имела 5 потоков (мастер и 4 воркера)
node.js - 3k rps / 30mspr - тут все понятно, тест не очень, тратится время на пробрасывание файл-дескриптора, на реальном приложении с логикой результаты думаю будут лучше
Go - к моему удивлению многопоточная производительность тоже упала до 7k rps / 15mspr
WTF? у Go ведь один параллельный процесс с общей памятью и файл-дескрипторами (или я чего то не знаю?) почему его производительность падает при многопоточности?
  • Вопрос задан
  • 572 просмотра
Пригласить эксперта
Ответы на вопрос 3
@SilentFl
1) обновитесь до 1.5.1.
2) вместо слоупочного ab возьмите хотя бы https://github.com/wg/wrk У меня, например, ab 16567 rps, wrk 45519 rps для 1.5.1
3) этот тест/код синтетика и показывает лишь только что у 1.2 планировщик не очень хорошо справляется на многоядерных архитектурах. на >1.5 ситуация должна быть другой. у меня на 1.5.1 для 1 потока 39637 rps, для 4х 45519 rps, если вообще не трогать gomaxprocs, то 48112 rps
Ответ написан
@kshvakov
runtime.GOMAXPROCS до Go 1.5 всегда был выставлен в 1. У вас версия Go какая ?
Ответ написан
Olej
@Olej
инженер, программист, преподаватель
у Go ведь один параллельный процесс с общей памятью и файл-дескрипторами (или я чего то не знаю?) почему его производительность падает при многопоточности?

Я не сильно разобрался в том, что вы описали, и уж тем более, по тесту и что и как вы тестировали (например по этой фразе - если процесс один, то кому он параллельный?).
Но у Go параллелизм (горутины) - это не то, что привычные потоки, там всё сложнее, поэтому могут видеться как побочные эффекты в тестах. Возможно вам поможет чем-то прояснить картину вот этот перевод: Планировщик Go.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы