Может ли поток на модель запроса быть быстрее, чем неблокирующий ввод-вывод? - PullRequest
8 голосов
/ 08 февраля 2011

Я помню, как 2 или 3 года назад читал пару статей, в которых люди утверждали, что современные библиотеки многопоточности становятся настолько хорошими, что серверы потоков на запрос будут не только легче писать, чем неблокирующие серверы, но они будут быстрее тоже. Я полагаю, что это было даже продемонстрировано в Java с JVM, которая отображала потоки Java в pthreads (т.е. издержки Java nio были больше, чем издержки переключения контекста).

Но теперь я вижу, что все «передовые» серверы используют асинхронные библиотеки (Java nio, epoll, даже node.js). Значит ли это, что async победил?

Ответы [ 4 ]

7 голосов
/ 08 февраля 2011

Не по моему мнению. Если обе модели хорошо реализованы (это БОЛЬШОЕ требование), я думаю, что концепция NIO должна преобладать.

В основе компьютера лежат ядра. Независимо от того, что вы делаете, вы не можете распараллелить ваше приложение больше, чем у вас есть ядра. Т.е., если у вас 4-х ядерный компьютер, вы можете делать ТОЛЬКО 4 вещи за один раз (некоторые детали приведены здесь, но для этого достаточно аргумента).

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

В идеале у вас есть один поток на ядро, и каждый из этих потоков работает на 100% скорости обработки на своем ядре. Переключение задач не происходит в идеале. Конечно, есть ОС, но если вы берете 16-ядерную машину и оставляете 2-3 потока для ОС, то оставшиеся 13-14 идут на ваше приложение. Эти потоки могут переключать то, что они делают в вашем приложении, например, когда они заблокированы требованиями ввода-вывода, но не должны платить эту стоимость на уровне операционной системы. Запишите это прямо в ваше приложение.

Отличным примером такого масштабирования является SEDA http://www.eecs.harvard.edu/~mdw/proj/seda/. Он показал гораздо лучшее масштабирование под нагрузкой, чем стандартная модель потока на запрос.

Мой личный опыт с Нетти. У меня было простое приложение. Я хорошо реализовал это как в Tomcat, так и в Netty. Затем я загружаю и проверяю его с сотнями параллельных запросов (более 800, я полагаю). В конце концов Tomcat замедлился до ползания и показал чрезвычайно бурное / медленное поведение. В то время как реализация Netty просто увеличила время отклика, но продолжила с невероятно общей пропускной способностью.

Обратите внимание, это зависит от надежной реализации. NIO все еще поправляется со временем. Мы учимся настраивать операционные системы наших серверов, чтобы лучше работать с ним, а также как внедрять JVM для более эффективного использования функциональных возможностей ОС. Я не думаю, что победитель еще может быть объявлен, но я верю, что NIO будет возможным победителем, и у него уже все хорошо.

6 голосов
/ 08 февраля 2011

Это быстрее, пока достаточно памяти.

Когда слишком много соединений, большинство из которых неактивны, NIO может сохранять потоки, следовательно, экономить память, и система может обрабатывать намного больше пользователей, чем модель потоков на соединение.

CPU здесь не является прямым фактором. В NIO вам необходимо самостоятельно реализовать модель потоков, которая вряд ли будет быстрее потоков JVM.

В любом случае память является самым узким местом. Когда нагрузка увеличивается и объем используемой памяти приближается к максимальному, GC будет очень занят, и система часто демонстрирует симптом 100% CPU.

4 голосов
/ 08 февраля 2011

Некоторое время назад я нашел довольно интересную презентацию , дающую некоторое представление о том, «почему старая модель потока на клиента лучше».Есть даже замеры.Однако я все еще обдумываю это.На мой взгляд, лучший ответ на этот вопрос - «это зависит», потому что большинство (если не все) инженерные решения являются компромиссами.

1 голос
/ 25 февраля 2011

Как говорилось в этой презентации, есть скорость и масштабируемость.

Один из сценариев, когда поток-на-запрос почти наверняка будет быстрее любого асинхронного решения, - это когда у вас относительно небольшое количество клиентов (например, <100), но у каждого клиента очень большой объем. например приложение реального времени, в котором не более 100 клиентов отправляют / генерируют 500 сообщений в секунду каждое. Модель потока на запрос, безусловно, будет более эффективной, чем любое асинхронное решение цикла событий. Async лучше масштабируется, когда есть много запросов / клиентов, потому что он не тратит впустую циклы ожидания на многих клиентских соединениях, но когда у вас мало клиентов с большими объемами при небольшом ожидании, это менее эффективно. </p>

Из того, что я видел, авторы Node и Netty оба признают, что эти платформы предназначены в первую очередь для решения проблем масштабируемости большого количества / многих соединений, а не для более быстрого решения для небольшого числа клиентов с большим объемом.

...