Что делает значительную разницу в производительности между eventlet и gevent?

эти две библиотеки разделяют аналогичную философию и аналогичные проектные решения в результате. Но!--16-->это популярный WSGI benchmark говорит eventlet намного медленнее, чем gevent. Что делает их выступления такими разными?

как я знаю, ключевые различия между ними:

  • gevent намеренно зависит и соединяется с libev (libevent, ранее), а eventlet определяет независимый интерфейс реактора и реализует определенные адаптеры с помощью select, epoll, и скрученный реактор за ним. делает ли дополнительный интерфейс реактора критические хиты производительности?

  • gevent в основном написано на Cython while eventlet написано на чистом Python. является ли изначально скомпилированный Cython настолько быстрее, чем чистый Python, для не очень вычислительных, но связанных с IO программ?

  • Первообразных gevent эмулировать стандартный интерфейсы библиотек в то время как eventletпримитивы отличаются от стандартных и обеспечивают дополнительный слой для его эмуляции. делает дополнительный слой эмуляцииeventlet медленнее?

  • реализация eventlet.wsgi просто хуже, чем gevent.pywsgi?

мне действительно интересно, потому что они в целом выглядят настолько похожими на меня.

2 ответов


Ну, gevent не "в основном", написанное на Cython, хотя некоторые критические секции.

Cython имеет огромное значение. Оптимизация процессора гораздо лучше работает с скомпилированным кодом. Прогнозирование ветвей, например, распадается в системах на основе виртуальных машин, потому что косвенное ветвление на уровне выполнения виртуальной машины непрозрачно для него. След кэша более плотный. Скомпилированный код имеет огромное значение здесь, и IO может быть очень чувствительным к задержке.

в аналогичным образом, libev очень быстро. Же причинам.

не похоже, что eventlet должен был использовать select hub (Python 2.6 обычно по умолчанию epoll). Если бы он застрял на select, это сделало бы его действительно медленный (потому что Python должен преобразовать select fd_set назад и вперед в список Python, поэтому он становится уродливым, когда он находится в середине цикла).

Я не делал никакого профилирования, но я готов поспорить, что libev / libevent plus Cython это большая разница. В частности, некоторые потоковые примитивы в Cython выступает в gevent. Это большое дело, потому что много кода затрагивает их косвенно через IO и даже стандартную библиотеку в некоторых местах.

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

сервер WSGI является еще одним сложным. Примечательно, что синтаксический анализ заголовка в gevent откладывается до стандартной библиотеки, тогда как они реализуют его сами в eventlet. Не уверен, что это большое влияние или нет, но было бы неудивительно, если бы там что-то скрывалось. Наиболее показательным является то, что сервер eventlet основан на версии стандартной библиотеки monkeypatched BaseHTTPServer. Я не могу представить, что это очень оптимальный. Gevent реализует сервер, который знает об эмуляции.


извините за поздний ответ.

есть две основные причины большой разницы в производительности в этом бенчмарке:

  • как уже говорилось ранее, критические пути gevent сильно оптимизированы
  • этот тест делает стресс-тестирование. Это больше не связано с IO, потому что он пытается заставить машину запускать как можно больше запросов. Вот где сияет Цитонизированный код.

"в реальном мире", что происходит только во время " slashdot" пробки на дорогах. Что важно и нужно быть готовым, но когда это происходит, вы реагируете, добавляя больше серверов или отключая тяжелые функции ресурсов. Я не видел тест, который фактически добавляет больше серверов при увеличении нагрузки.

Если, с другой стороны, benchmark будет имитировать "нормальную дневную" нагрузку (которая будет варьироваться от одного веб-сайта к другому), но в целом может быть аппроксимирована запросом, случайной паузой, повторением. Чем меньше пауза - тем больше трафика мы имитируем. Также клиентская сторона benchmark должна будет имитировать задержку. В Linux это можно сделать с помощью awesome netem[1], в противном случае, поставив небольшие задержки перед вызовами recv/send (что было бы очень сложно, потому что бенчмарки обычно используют библиотеки более высокого уровня).

теперь, если эти условия будут выполнены, мы фактически проверим связанные с IO проблемы. Но результаты не были бы слишком удивительными: все кандидаты успешно обслуживали нагрузки 10, 50 и даже 200 qps. Скучно, правда? Так мы смогли измерить распределение задержки, время для обслуживания 99% запросов и т. д. Gevent бы все-таки покажет лучшие результаты. Но разница вряд ли впечатлит.

[1] имитация задержанных и сброшенных пакетов в Linux