因此,这两个库具有相似的理念和相似的设计决策。但是this popular WSGI benchmark说eventlet
比gevent
慢得多。是什么使他们的表现如此不同?
据我所知,它们之间的主要区别是:gevent
有意依赖并耦合到libev
(以前称为libevent
),而eventlet
定义了独立的反应堆接口,并在其后使用select
,epoll
和Twisted Reactor实施了特定的适配器。附加的反应堆接口是否会严重影响性能?gevent
主要用Cython编写,而eventlet
用纯Python编写。对于不是那么计算但需要IO约束的程序,本地编译的Cython是否比纯Python快?gevent
的基元模拟标准库的接口,而eventlet
的基元与标准库不同,并提供了更多的层来模拟它。附加的仿真层会使eventlet
变慢吗?eventlet.wsgi
的实现是否比gevent.pywsgi
差?
我真的很奇怪,因为它们总体上对我来说是如此相似。
最佳答案
嗯,尽管有些关键部分是用Cython编写的,但gevent不是“主要”。
Cython产生了巨大的变化。处理器优化在编译后的代码中效果更好。例如,分支预测在基于VM的系统中会崩溃,因为在VM执行级别上分支的间接性对其并不透明。缓存占用空间更小。编译后的代码在这里有很大的不同,并且IO对延迟非常敏感。
同样,libev非常快。相同的原因。
似乎eventlet不应一直使用select集线器(Python 2.6通常默认为epoll)。但是,如果将它卡在select上,那将使其真正变慢(因为Python必须将select fd_set来回转换为Python列表,因此当它处于循环中间时,它会变得难看)。
我没有做任何分析,但我敢打赌libev / libevent加上Cython会带来很大的不同。值得注意的是,某些线程原语位于gevent的Cython中。这很重要,因为很多代码通过IO甚至是某些地方的标准库间接地触摸了它们。
至于eventlet的附加仿真层,确实存在更多的反弹性。在gevent中,代码路径似乎构造了回调并让中心调用它们。 eventlet似乎完成了中心在gevent中所做的记账工作。同样,我还没有介绍它。至于monkeypatching本身,它们看起来非常相似。
WSGI服务器是另一个难题。值得注意的是,gevent中的标头解析被推迟到标准库中,而它们自己在eventlet中实现。不知道这是否会带来很大的影响,但是如果其中潜伏着什么也就不足为奇了。最能说明问题的是,eventlet的服务器基于标准库BaseHTTPServer的monkeypatched版本。我无法想象这是非常理想的。 Gevent实现了一个知道仿真的服务器。