Как стать автором
Обновить

Комментарии 54

В ходе разговора с авторами nginx они несколько раз упомянули, что для нагрузочного тестирования используют ab из apache и wrk (https://github.com/wg/wrk)
Для тестирования я использую Tsung и siege.
Без измерения cpu/memory usage это все не имеет смысла
Присоединяюсь. Важно, насколько ресурсы компа заняты во время обработки этого потока запросов. Интересно было бы создать фоновую нагрузку, например, архивировать файлы или mp3/mp4 конвертировать. Может быть, это подвинет позиции.
А сейчас — это если весь сервак выделен под эту задачу. Если так, то тоже интересно, сколько этого сервера «пропадает».
Я думаю, с теми объемами пересылаемых данных, которые упоминает в статье автор, сервер очень вряд ли занимается чем-либо еще, кроме диспетчеризации. :)
Поддерживаю предыдущего оратора.

Автор, прости. Статья интересная. Я — нуб.
Но мне очень, жалко ноду, поэтому я всю ночь не спал и запилил топик добра.
Колонки «Время(польз.\сист.)» в таблице результатов — это psutil get_cpu_times() для родительского и дочерних процессов сервера.
Память не мерялась в силу того, что ни один участник не использовал этот ресурс сколько-нибудь значительно (кроме node.js, о чем есть упоминание).
Ноджс — хайлоад-решение? Хахаха, то есть мяу
если вы его не умеете готовить — так оставьте это тем, кто умеет :)
Да, можно, конечно — поделим ядра, оставив минимум одно самой системе, чтобы не блокировать сетевой стек:

 exec('taskset -pc ' + affinity + ' ' + pid);


Естественно, это у this.isCluster == true, чтобы форки тоже попали в affinity.
Дальше оно само разберётся.

Поправим конфиги по типу как у автора + ulimit, kernel.sem и т.п..

Статику всё равно лучше через nginx, что правда — то правда, это ещё минус одно ядро.
Зато в разработке логики всё будет просто и шоколадно :)
Я node.js использовал ещё в версии 0.2, когда там были прямые posix-вызовы, что все сильно упрощало. Это хороший инструмент для ряда задач, но из другого эшелона. Тот же PHP с libev даёт сравнимую производительность, но у меня язык не двинется назвать это хайлоад-решением. Вокруг ноджса слишком много пиара.
>> httperf с его линуксовым select-ом

Все-таки select это не линуксовый вызов, а вездесущий, я бы сказал, мультиплатформенный в общем.
Кстати, не хватает теста чистой libuv ;)
За графики конечно спасибо — очень познавательно, но половина результатов я уже понял в априори.
Сам уже давно юзаю libevent & libev. В своё время делал счетчик кликов для баннерки на libevenet. Держала миллионы запросов в сутки — подтверждаю.

Может в этот зоопарк можно было добавить gwan. Он как раз для таких задач, как счетчики.
Однако, каждой твари по паре, каждому HTTP серверу по своей задачи.
А чего в год цифру не дали? Миллиарды получились бы. 1 000 000 запросов в сутки — это 11.5 rps, нехитрая математика подтверждает.
К сожалению, gwan очень сильно завязан на linux — окружение. Было бы интересно узнать, что представляет из себя этот выделяющийся на фоне остальных серверов своей весьма агрессивной рекламой сервер.
Интересное исследование, спасибо. Да, наибольшее разочарование — node.js
Скорее всего, она всё-таки была неправильно приготовлена, кто-то наверное что-то упустил.
Ноде нельзя отдавать всё, т.к. она всё и сожрёт.

Чуть выше отписался.
Клиент и сервер запускались на одной и той же физической машине

так низзя…
Спорный вопрос, смотря какие стоят цели и задачи. Если это нагрузочный прогон системы перед запуском в продакшн — то однозначно localhost не подходит. Если же это тестирования сферических ядер на лабораторном стенде — localhost вполне жизнеспособное решение.
одно из мнений «за» (раздел Why localhost tests are relevant?)
ИМХО — очень сферический в вакууме тест.
Процессоры считают последовательно, и доверять ядру распределение нагрузки многопоточных задач никак нельзя.
Интересно было бы посмотреть, если бы автор оставил 6 ядер серверу, одно системе, одно CURL'у.
А так — на переключение контекста очень много времени будет уходить.
Может я чего-то не то скажу, но я всегда считал, что epoll это в linux, а во FreeBSD это kqueue. (onion и poco из тестируемых образцов). Разве нет?
Вы правы, для onion в FreeBSD механизм событий при сборке по-умолчанию — libev.
poco (из портов) — в FreeBSD использует select.
CPU: AMD FX(tm)-8120 Eight-Core Processor
Количество серверных потоков (1 и 8).
client_threads = psutil.NUM_CPUS
Клиент и сервер запускались на одной и той же физической машине.
Т.е. в вашем тесте клиент и сервер весьма жестко конкурировали за ресурсы, и кому-то их лучше удалось поделить между собой.

Кроме того ваш процессор снабжен технологией Turbo Core 2, которая в зависимости от нагрузки и TDP/ACP может весьма своеобразно повышать частоту отдельных ядер. Надеюсь в процесее испытания она была отключена?
Контроль за ресурсы — по сути все сервера находятся в одинаково невыгодном положении, надеялся компенсировать это результатами, построенными на многократных запусках (более ста итераций на каждый сервер). Но согласен — это один из самых спорных моментов в данной статье. Никогда не слышал про Turbo Core 2, еще раз убеждаюсь, что идеальных бенчмарков не бывает, слишком много влияющих параметров.
Перегнал тесты по nginx с worker_processes = 8 и выключенным AMD Turbo Core и Cool'n'Quiet.
Результаты — минус 1-2 процента производительности почти по всем итерациям (макс. результат — 136485, упал до 135620 (-0.6%).
Утверждение о влиянии AMD Turbo Core выглядит сомнительным.
К вопросу о тестировании на разных машинах — какие модели сетевых карт были бы приняты за достоверно отображающие производительность? Например, подходит ли для адекватного тестирования Broadcom BCM57780? Realtek RTL8139? Что можете сказать о свиче?
У вас система с worker_processes = 8 упирается вовсе не в сервер. По опыту, системные вызовы клиентской части тяжелее, и чтобы упереться в nginx нужно под клиент выделить существенно большие ресурсы.

Я могу рассказать, как я замеряю. 12-ти (физических, вирутальных 24) ядерный сервер. Если вопросы скалирования не интересуют (нужно определится, что измеряем — скалирование или производительность, а мешать всё в кашу — нельзя), то тестировать имеет смысл только с одним рабочим процессом. Выставляем worker_processes 1; и worker_cpu_affinity (последнее особенно для FreeBSD актуально, ибо планировщик там может чудить). Динамическое скалирование частоты процессора отключаем, система чистая, никаких cron-задач, работающих фоновых служб и прочего. Берем клиент (самый производительный из известных мне — wrk, остальные становятся узким местом раньше) и запускаем цикл измерений в 8 потоков (ещё 3 физических ядра пригодятся системе) — 30-100 измерений по 30-120 секунд, замеры сохраняем в файл для последующего анализа с помощью ministat (числа без указания погрешностей — можно рассматривать только ради развлечения). Применение всех изложенных мер позволяет получить относительную погрешность в пределах 2% (ни о каких 0.6% разницы речи идти не может, на реальной системе едва ли сможете измерить с такой точностью).

В вашем тесте вы скорее всего протестировали weighttpd с помощью разных серверов (а не наоборот). Какой из них имеет паттерн обработки запросов более согласующийся с упомянутой утилитой, таким образом входя в резонанс при определнных условиях. Для получаения более-менее достоверных результатов клиент должен обладать запасом по производительности минимум раза в 2-3 превосходящим сервер, а в идеале на порядок.
Т.е. на моей конфигурации (8 физических ядер) достаточно будет 1 рабочего процесса (с заданным аффинити), 4 потока клиента (3 ядра остается системе), 30-100 измерений по 30-120 секунд. Ок, прогоню такие тесты с weighttp и wrk, результаты предоставлю.
Пока все в процессе, но первые (грубые) результаты по вашей методике (1 серв. процесс с афинити, 4 потока клиента с аффинити) аналогичны результатам из моих первоначальных тестов (там ведь тоже были режимы с 1 серв. процессом). nginx в этом режиме опережает остальных топовых участников в 2.5 раза. Ваш комментарий по этому поводу, как разработчика nginx?
Кстати, wrk показал 1-3% прирост по сравнению с weighttp. Подробные результаты будут позже…
Так я уже выше об этом и написал, что в остальных режимах вы упираетесь не в веб-сервер, а в бенчмаркалку. В nginx практически нет взаимодействия между процессами и единственным узким местом может стать только слушающий сокет, а до тех пор производительность должна расти линейно с увеличением числа рабочих процессов.

В тот момент же, когда вы упираетесь в бенчмаркалку то возникают всякие пограничные эффекты. Помню год назад один человек написал в рассылку, он тестировал с помощью ab и с удивлением обнаружил, что выключение логов дает не прирост производительности, а наоборот — регрессию. Включая access_log он стабильно наблюдал заметно больший rps. Я изучил этот случай, и вот что выяснилось: с выключенными логами рабочий процесс nginx-а то и дело уходил в спячку, ab не успевал прислать следующий запрос после завершения обработки всех предыдущих, но если включить логи, то лишний write() строчки лога на диск на каждый запрос чуть подтормаживал процесс и ab чаще успевал прислать запрос, так что nginx не оставался совсем без работы и не засыпал, последнее оказывалось существенно дороже записи логов.
Результаты обновлены.
Node.js — не хайлоад-решение и никогда так не позиционировался. Он «быстрый» в смысле «быстрее, чем аналогичные решения на других скриптовых языках — Python, Ruby, Perl, PHP», а не в смысле «быстрее всех». Члены команды разработки Node.js даже никогда не обсуждают его скорость в сравнении с Go, Rust, C++ и другими компилируемыми языками. Не сравнивают они его и с высокопроизводительными VM типа Java или .NET: у тех в запасе почти 2 десятка лет работы над производительностью. Сегодняшний V8 по уровню развития как раз сравним с JVM примерно десятилетней давности.

В вашем конкретном случае в дополнение к собственно работе с HTTP ему еще приходится запускать виртуальную машину, заниматься сборкой мусора и JIT-компилировать код и т.д. Поэтому сравнивать его с Nginx или libevent вообще не имеет смысла. Вы же не сравниваете скорость болида Формулы 1 и тролейбуса, правда?
PayPal — хайлоад? Как прокомментируете перевод фронтов (для начала) с JVM на Node.js. Ещё из списка: Ebay's ql.io, Linkedin, Wallmart, Trello, Groupon и ещё. Что для вас хайлоад? Сотня млн. запросов в день, норм? А несколько сотен?

П.С. Разница в 3х между, к примеру, nginx и node.js — всё-таки это как Формула 1 и, скажем, средний спорткар, но не троллейбус :).
Вы ж понимаете, что это громкие слова. По пунктам:

PayPal: переводят сайт на NodeJS с Java. Процессинг платежей так и остается на смеси Java и C++, и планов по миграции на что-то другое для этих задач нет. Цель миграции для сайта — иметь возможность быстро менять наполнение, проводить A/B тесты для конверсий и т.д. Т.е. сугубо маркетинговые задачи. С той же легкостью они могли мигрировать на Django или Rails — им просто нужен был инструмент, позволяющий работать с фаннелом в очень сжатые сроки. Ну и сами понимаете, сайт для них — это не узкое место в плане производительности.

Walmart и LinkedIn: Node.js используется как прокси для мобильных сервисов. Весь тяжелый процессинг так же остается на стороне Java. Поэтому неудивительно, что на Black Friday в волмарте Нод вел себя спокойно — он также не был узким местом.

Групону до перехода хватало производительности Рельсов. Тот факт, что Node.js им подошел, меня нисколько не удивляет. Кроме того, при переходе ребята сильно переработали архитектуру всего сервиса, и основной выигрыш в производительности поличили именно от этого, а не от скорости v8.

Trello — небольшой проект. Называть хайлоадом все, что смотрит в интернет, я бы не стал.

ql.io мертв уже больше года. Но даже когда он еще жил, он был «research»-проектом и никогда не процессил больших объемов данных. В инфраструктуре Ebay он не используется. Ближайший аналог — YQL — крутится на JVM+Rhino, и там нагрузки действительно колоссальные.

> Что для вас хайлоад? Сотня млн. запросов в день, норм? А несколько сотен?

Хайлоад не начинается с какой-то четкой границы. И не зависит только от запросов в секунду. Например, допустим, у нас есть сервис, в котором нет сетевых эффектов: у каждого пользователя свой набор данных и никто не запрашивает чужие данные: т.е. нет никакого обмена сообщениями, общих документов, одновременного редактирования и т.п. Один железный бокс в такой системе обслуживает 50 пользователей с комфортным запасом по производительности. У нас 5 миллионов пользователей, и для них мы подняли 100 тысяч таких боксов, пошардили данные и настроили лоад-балансер и автозамену падающих узлов. Если их станет в два раза больше, мы просто поднимем в 2 раза больше боксов, и за исключением выросших затрат на хостинг, к никаким другим последствиям это не приведет. Хайлоад ли это?

А вот если есть сетевые эффекты, то рост пользовательской базы в 2 раза может легко привести к тому, что какие-то части системы не смогут работать без значительной переработки. Вот именно такие «узкие места» в производительности в моем понимании — хайлоад. В Фейсбуке это рассылки уведомлений, сообщений, обновление новостных лент. А вот система загрузки фотографий явно скейлится линейно с ростом нагрузки, и хайлоадом при всем количестве железа может быть названа только с натяжкой.

Во всех вышеперечисленных примерах Node.js, хоть и является частью большой системы, но не оказывается узким местом в плане роста инфраструктуры, поэтому заслуги платформы в успехе данных проектов практически нет. На месте Node.js мог оказаться Питон, Руби, PHP или Perl, и ничего бы кардинально не поменялось.

И да, Нод я люблю и на нем работаю. В нашем проекте есть части на Node.JS, Erlang, Java, Python, и несмотря на миллионы пользователей и большую нагрузку, я не могу назвать части, написанные на NodeJS, хайлоадом. Узкие места сейчас для нас покрывают Erlang и Java — там хайлоад есть. Показательно, что именно из-за них мне приходится иногда просыпаться по ночам. Из-за Node.js я не просыпаюсь не потому, что он супер-надежный, а потому, что он не находится на критическом пути.

В этих компаниях та же ситуация, и я уверен, что пока Эран и его друзья смотрели на равные графики нодовских процесссов, ребятам из отделов бекенд-сервисов Волмарта пришлось изрядно попотеть.

Единственный хайлоад-проект на Ноде, о котором мне известно — это Voxer.
Ну почему же громкие слова? Как раз-таки я посчитал ваше утверждение "Node.js — не хайлоад-решение" — весьма смелым. Я с этим не согласен и, уверен, парни из PayPal тоже. Нода не для тяжёлой логики (и вообще чего-либо CPU-intensive), это да.

Ваша мысль понятна, для вас хайлоад определяется тяжеловестностью выполняемой логики (которую выполняют, как правило, бэкэнды). Это логично. Но вот возьмём два 8-ядерных commodity-сервера: на одном Java/C[++] обрабатывает какую-нибудь длинную очередь HD-видео от 100 клиентов, загружая под 100% все ядра; на другом крутится Нода с 7 форками (с лёгкой логикой, вроде отдачи из кэша), крутится хорошо, на 40K RPS, тоже загружая под 100% сервер. Первое — хайлоад (что очевидно), а второе тогда что, если не хайлоад?

Как тогда, по-вашему, называть, допустим, отдачу статики 15 млн. пользователям ежедневно? Ну вот нету ничего тяжелого в проекте (к примеру всякого рода t.co/bit.ly, хостеры картинок и т.п.).

То, что грамотное горизонтальное маштабирование позволяет использовать %language% — это понятно. Также понятно, что для тяжёлой логики есть JVM / .NET / компилируемые языки.

Во-вторых, скорость работы и стабильность для конечного пользователя — критически важный показатель для такой системы как PayPal (всё-таки не хостинг картинок с котиками). Ежедневно через систему проходят платежи на сотни млн. $.

Факт того, что PayPal переводит эту часть (фронты) на Ноду, вполне говорит нам, что она production ready && highload ready.
Из того, что я про него читал здесь (раздел How is it so fast?), в node.js нет оверхедов на JIT-компиляцию и виртуальная машина не вовлечена в процесс, незнаю насколько это соотвествует действительности.
На практике помню, что GC практически полностью парализовывал работу сервера.
До тех пор, пока последовательное выполнение инструкций будет основой архитектуры информационных систем, нужно всё таки делать поправки на ветер. Самой системе нужно оставлять хоть что-нибудь, хоть одно ядро, чтобы она жила.

Можно почитать что-нибудь типа Ч. Петцольд — Код
Из вашей статьи:

It’s speed comes from the fact that it compiles JavaScript directly into native assembly.


Таки Jit-компиляция есть, сборка мусора есть. Т.е. оверхед есть.
Не происходит ли Jit-компиляция единожды, в момент запуска скрипта?
Нет, там компиляция проходит в несколько этапов: вначале генерируется неоптимизированный код, а затем по ходу его выполнения собирается информация о частоте вызова методов и фактических типах параметров и переменных. По этим данным собирается оптимизированный код. Если в какой-то момент встречается какой-то новый тип, то приходится возвращаться к первоначальному варианту кода, но данные продолжают собираться, чтобы подготовить новый оптимизированный вариант. В сложных случаях — в частности в NodeJS этой бедой страдает EventEmitter — виртуальная машина вынуждена оптимизировать и деоптимизировать одни и те же функции снова и снова.
Недавно занимался нагрузочным тестированием и открыл для себя httpress: bitbucket.org/yarosla/httpress/wiki/Home По производительности он показал себя лучше, чем ab, хотя у ab более подробная статистика прогона.
Утилита от создателя дисквалифицированного nxweb. По заявлению автора — Inspired by weighttp tool, синтаксис ком. строки полностью совпадает.
Компиляция осложнена linux-зависимостями типа sys/sendfile и memalign (патчится легко).
При запуске выкидывает кучу ошибок соединения, потом тесты проходят, результат аналогичен weighttp.
Других различий не обнаружил.
Компиляция осложнена linux-зависимостями типа sys/sendfile и memalign (патчится легко).

с чего бы вдруг сендфайл стал linux-зависимостью?! :) тем более, что в freebsd/solaris он тоже есть?

и для генератора нагрузки sendfile() не нужен. разьве что для POST'а.
sendfile
Not specified in POSIX.1-2001, or other standards.
Other UNIX systems implement sendfile() with different semantics and prototypes. It should not be used in portable programs.
В данной утилите он не нужен, но он там почему-то есть.
я знал, что вы туда сошлётесь :) ну нет в posix.1-2001… и что? :)
linux-зависимость — это epoll/splice/vmsplice/fincore. но явно не достаточно портабельный sendfile.
ну нету в FreeBSD файла sys/sendfile.h :) (и нигде нет, кроме linux).
Это все про общую «небрежность» кода, что заставляет задуматься об использования этой тулзы в любых тестах.
с чего бы вдруг сендфайл стал linux-зависимостью?! :) тем более, что в freebsd/solaris он тоже есть?
Он в этих системах разный. В nginx, например, для FreeBSD, Linux, Solaris и Darwin — 4 отдельных реализации, везде есть нюансы.
Удивительно, как меняется мир. Добавить apache никому даже в голову не пришло.
Признаться — была такая мысль, но как-то не попалось готового модуля, который можно быстро переделать под нужды тестирования (все больше какие-то пространые мануалы с вовлечением apxs и прочих ужасных вещей). Та же участь постигла lighttpd. Но это, я думаю, и не страшно — тут тестируются C/C++ библиотеки/фреймворки, nginx и node.js приведены лишь для сравнения с миром «готовых» HTTP-серверов. А так да — в черновиках была целая простыня из mongrel, cherokee и т.п.
НЛО прилетело и опубликовало эту надпись здесь
А вообще, методика тестов странная, как и выводы.
настройки sysctl.conf странные, mbuf-кластеров мало, цифр по netstat/vmstat -z нет.

я писал однопоточный http-сервер на python(gevent) и без каких-либо ухищрений он выдавал 11k rps. тесты выполнялись на реальном железе через линк в 1GEx2.
это написанное на интерпретируемом языке и без jit. есть у меня мысли перенести это на pypy и посмотреть цифры.
В системе настройки не менялись, они не давали прироста производительности (см. параграф под настройками в статье).
Какой утилитой тестили python сервер?
НЛО прилетело и опубликовало эту надпись здесь
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.