Преамбула:
На старте разработки сайта, от которого ожидается высокая нагрузка. Соответственно выбор между 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 ведь один параллельный процесс с общей памятью и файл-дескрипторами (или я чего то не знаю?) почему его производительность падает при многопоточности?
bingo347: кстати, вы там писали, что go у вас 1.2.чтототам. Это очень старый go. Последний релиз сейчас 1.5.1
А код попробую погонять потом.
Написано
Дмитрий Беляев
@bingo347 Автор вопроса, куратор тега Node.js
Александр Павлюк: да, я вкурсе про 1.5 и о том что в нем много чего переделали, как уже писал выше на Go я еще не разрабатывал ничего серьезного (а может и не стоит браться пока?) поэтому и стоит версия из apt-get (в репах убунты редко бывает свежая софтина не на массового пользователя)
А если погоняете код, заранее спасибо
Написано
Дмитрий Беляев
@bingo347 Автор вопроса, куратор тега Node.js
обновил go до 1.5.1
пример выше выдает 7k rps при 4 потоках (с явным указанием GOMAXPROCS или вовсе без него) и 7.5k rps при явном указании 1 потока
возможно конечно дело в том что в ос в данный момент работает много других процессов и некоторые потоки go ложатся на одно ядро, а время тратится на переключение контекста, но все равно это странно, что 4 потока работают медленнее чем 1
попробую нагрузить запросы какими нибудь вычислениями + парой асинхронных операций, чтоб приблизить это все к реальности, может что и изменится
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
у Go ведь один параллельный процесс с общей памятью и файл-дескрипторами (или я чего то не знаю?) почему его производительность падает при многопоточности?
Я не сильно разобрался в том, что вы описали, и уж тем более, по тесту и что и как вы тестировали (например по этой фразе - если процесс один, то кому он параллельный?).
Но у Go параллелизм (горутины) - это не то, что привычные потоки, там всё сложнее, поэтому могут видеться как побочные эффекты в тестах. Возможно вам поможет чем-то прояснить картину вот этот перевод: Планировщик Go.