Python Requests与PyCurl性能对比

60

Requests库和PyCurl在性能上有何比较?

据我了解,Requests是urllib的Python包装器,而PyCurl是libcurl的Python包装器,后者是本地的,因此PyCurl应该具有更好的性能,但不确定提升多少。

我找不到任何性能比较基准。

4个回答

137

我为你编写了一个完整的基准测试,使用一个简单的Flask应用程序,并以gUnicorn/meinheld + nginx作为支持(用于性能和HTTPS),并查看完成10,000个请求需要多长时间。测试在一对未加载的c4.large实例上在AWS上运行,服务器实例未受CPU限制。

简短摘要:如果你正在处理大量网络操作,请使用PyCurl;否则,请使用requests。PyCurl可以比requests快2倍到3倍来完成小型请求,直到你达到带宽限制为止(在这里约为520 MBit或65 MB/s),并且使用的CPU功率从3倍到10倍不等。这些数字比较了连接池行为相同的情况;默认情况下,PyCurl使用连接池和DNS缓存,而requests则没有,因此朴素实现将慢10倍。

Combined-chart-RPS CPU Time by request size detailed

Just HTTP throughput Just HTTP RPS

请注意,由于涉及数量级的原因,下面的图形使用双对数图。 HTTP & HTTPS throughput HTTP & HTTPS RPS

  • 当重用连接时,pycurl需要约73个CPU微秒发出请求
  • 当重用连接时,requests需要约526个CPU微秒发出请求
  • 当打开新连接并发出请求(不重用连接)时,pycurl需要约165个CPU微秒,或者大约92个微秒来打开连接
  • 当打开新连接并发出请求(不重用连接)时,requests需要约1078个CPU微秒,或者大约552个微秒来打开连接
  • 完整结果可在此链接查看,其中包括基准测试方法和系统配置。

    注意:尽管我已经努力确保结果以科学的方式收集,但它只测试了一个系统类型和一个操作系统,并且是性能特别是HTTPS选项的有限子集。


3
您的基准测试很不错,但本地主机没有任何网络层开销。如果您能够以实际网络速度为界限限制数据传输速度,使用真实的响应大小(pong 不太现实),并包含混合的内容编码模式(有压缩和无压缩),然后基于此生成计时数据,那么您就会得到具有实际意义的基准测试数据。 - Martijn Pieters
我还注意到您将pycurl的设置移出了循环(设置URL和writedata目标应该是循环的一部分),并且没有读取cStringIO缓冲区;所有非pycurl测试都必须将响应作为Python字符串对象生成。 - Martijn Pieters
3
@MartijnPieters,缺少网络开销是有意为之的;这里的目的是在隔离的客户端中进行测试。该URL是可插拔的,因此您可以根据需要将其测试到真实的、活动的服务器上(默认情况下不会这样做,因为我不想影响某人的系统)。重要提示:后面使用pycurl进行的测试通过body.getvalue读取响应正文,并且性能非常相似。如果您可以提出改进建议,欢迎提交代码的PR。 - BobMcGee
1
@KennethReitz 是的,这是一个相当粗略的基准测试,如果你已经有了改进,我欢迎PR(并可以在原始系统上重新运行以进行苹果对苹果的比较)!我们真的应该为所有情况都有连接重用和无连接重用的基准测试覆盖率。这是因为一个人可能会向不同的服务器发出请求或向同一个服务器发出一系列请求。根据你的数据,我认为我们仍然可以说,在相同的连接行为下,pycurl 的速度比其他方式快 3 到 10 倍。 - BobMcGee
2
@Martijn_Pieters 你可能需要再看一下,我已经更新了在AWS中包含完整网络开销的基准测试。 - BobMcGee
显示剩余8条评论

21

首先,requests 是基于 urllib3 构建的,而标准库中的 urlliburllib2 库根本没有使用。

在性能方面,比较 requestspycurl 没有太大意义。虽然 pycurl 可能会使用 C 代码进行工作,但像所有网络编程一样,你的执行速度主要取决于分隔您的机器与目标服务器的网络。此外,目标服务器可能响应缓慢。

最终,requests 有一个更加友好的 API,您会发现使用这个更友好的 API 会提高您的生产力。


4
我同意对于大多数应用程序而言,requests 的简洁 API 最为重要;但对于网络密集型应用程序,没有理由不使用 pycurl。尤其是在数据中心内,开销可能很重要。 - BobMcGee
4
如果网络速度非常快,开销很重要,那么你就不应该再全程使用Python来开发应用程序。 - Martijn Pieters
4
我不同意——Python 的性能并不那么差,通常很容易将对性能敏感的部分委托给本地库(例如 pycurl)。DropBox 可以运行,yum 内部也使用了 pycurl(因为它需要尽可能快地进行网络获取)。 - BobMcGee
1
@BobMcGee:是的,对于像yum这样的专业代码库来说,处理pycurl API的痛苦可能是值得的;然而,对于绝大多数URL处理需求来说,权衡更倾向于使用“requests”。换句话说,大多数项目不需要经历使用“pycurl”的痛苦;在我看来,你需要在网络方面非常重视才值得放弃“requests”API;开发的便利性差异是巨大的。 - Martijn Pieters
2
@MarijnPieters:完全同意!除非网络性能关键(或需要低级curl功能),否则应该使用Requests作为默认工具。为了完善这个画面,我们现在有一个基准测试可以供某些人自行测试。 - BobMcGee

8

似乎有一个新的选择:使用pycurl的requests接口。

非常感谢您提供的基准测试,很棒。我喜欢curl,看起来它可以比http做更多的事情。

https://github.com/dcoles/pycurl-requests


2

专注于文件大小 -

  1. 在我的Mac Book Air上,配备8GB RAM和512GB SSD,对于一个100MB的文件,每秒传输速度为3KB(来自互联网和wifi),无论是使用pycurl、curl还是requests库的get函数(无论是分块还是流式传输),它们的表现几乎相同。

  2. 在一台更小的四核Intel Linux盒子上,配备4GB RAM,在本地主机(从同一台主机上的Apache服务器)上,对于一个1GB的文件,curl和pycurl比'requests'库快2.5倍。而对于请求分块和流式传输的组合,可以提高10%的性能(块大小大于50,000)。

我原以为需要将requests替换为pycurl,但由于我正在制作的应用程序不会有那么紧密的客户端和服务器,所以不需要这样做。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接