因此,这两个库具有相似的理念和相似的设计决策。但 这个流行的 WSGI 基准eventletgevent. 。是什么让他们的表现如此不同?

据我所知,它们之间的主要区别是:

  • gevent 有意依赖于并耦合到 libev (libevent, ,之前)同时 eventlet 定义独立的反应器接口并使用特定的适配器实现 select, epoll, ,以及它后面的扭曲反应堆。 额外的反应器接口是否会对性能产生关键影响?

  • gevent 大部分是用 Cython 编写的 eventlet 是用纯Python编写的。 对于计算量不大但受 IO 限制的程序,本机编译的 Cython 是否比纯 Python 更快?

  • 的原语 gevent 模拟标准库的接口,同时 eventlet的原语与标准不同,并提供额外的层来模拟它。 额外的仿真层是否可以使 eventlet 慢点?

  • 是否实施 eventlet.wsgi 只是比 gevent.pywsgi?

我真的很想知道,因为它们对我来说总体看起来非常相似。

有帮助吗?

解决方案

好吧,gevent 并不是“大部分”是用 Cython 编写的,尽管有些关键部分是用 Cython 编写的。

Cython 带来了巨大的改变。处理器优化对于编译代码效果更好。例如,分支预测在基于 VM 的系统中会崩溃,因为 VM 执行级别的分支的间接性对它来说是不透明的。缓存占用空间更小。编译后的代码在这里会产生巨大的差异,并且 IO 对延迟非常敏感。

同样,libev 也非常快。同样的原因。

eventlet 似乎不应该使用 select hub(Python 2.6 通常默认为 epoll)。不过,如果它卡在选择上,那就可以了 真的 慢(因为Python必须将select fd_set来回转换为Python列表,所以当它处于循环中间时它会变得很难看)。

我还没有做过任何分析,但我愿意打赌 libev / libevent 加上 Cython 会带来很大的不同。值得注意的是,一些线程原语位于 Cython 的 gevent 中。这是一件大事,因为很多代码通过 IO 甚至在某些地方通过标准库间接接触它们。

至于 eventlet 的附加模拟层,似乎确实有更多的弹性。在gevent中,代码路径似乎构造回调并让集线器调用它们。eventlet 似乎比 hub 在 gevent 中做更多的簿记工作。不过,我还没有对它进行简介。至于猴子补丁本身,它们看起来非常相似。

WSGI 服务器是另一个困难的服务器。值得注意的是,gevent 中的头解析被推迟到标准库,而他们自己在 eventlet 中实现它。不确定这是否会产生很大的影响,但如果其中潜伏着什么东西也就不足为奇了。最能说明问题的是,eventlet 的服务器基于标准库 BaseHTTPServer 的 Monkeypatched 版本。我无法想象这是非常理想的。Gevent 实现了一个能够感知模拟的服务器。

其他提示

抱歉回复晚了。

性能差异较大的主要原因有两个 在那个基准中:

  • 如前所述,gevent 的关键路径经过大量优化
  • 该基准进行压力测试。它不再受 IO 限制,因为它试图让机器运行尽可能多的请求。这就是 Cythonized 代码的闪光点。

“在现实世界中”这只发生在“slashdot”流量爆发期间。这很重要,应该做好准备,但是当这种情况发生时,您可以通过添加更多服务器或禁用资源密集型功能来做出反应。我还没有看到在负载增加时实际添加更多服务器的基准测试。

另一方面,如果基准测试会模拟“正常一天”的负载(每个网站的负载会有所不同),但通常可以近似于请求,随机暂停,重复。停顿越少,我们模拟的流量就越多。此外,基准测试的客户端必须模拟延迟。在Linux上,这可以使用awesome netem[1]来完成,否则,可以通过在recv/send调用之前放置小的延迟来完成(这将非常困难,因为基准测试通常使用更高级别的库)。

现在,如果满足这些条件,我们实际上将对 IO 限制问题进行基准测试。但结果不会太棒:所有候选者都成功服务了 10、50 甚至 200 qps 负载。无聊,对吧?因此我们可以测量延迟分布、服务 99% 请求的时间等。Gevent仍然会表现出更好的结果。但这种差异很难给人留下深刻的印象。

[1] 在 Linux 上模拟延迟和丢包

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top