繁体   English   中英

为什么Python 3 http.client比python-requests快得多?

[英]Why is Python 3 http.client so much faster than python-requests?

我今天正在测试不同的Python HTTP库,我意识到http.client库的执行速度比requests快得多。

要测试它,您可以运行以下两个代码示例。

import http.client

conn = http.client.HTTPConnection("localhost", port=8000)
for i in range(1000):
    conn.request("GET", "/")
    r1 = conn.getresponse()
    body = r1.read()
    print(r1.status)

conn.close()

这里是与python-requests做同样事情的代码:

import requests

with requests.Session() as session:
    for i in range(1000):
        r = session.get("http://localhost:8000")
        print(r.status_code)

如果我启动SimpleHTTPServer:

> python -m http.server

并运行上面的代码示例(我正在使用Python 3.5.2)。 我得到以下结果:

http.client:

0.35user 0.10system 0:00.71elapsed 64%CPU 

蟒蛇,请求:

1.76user 0.10system 0:02.17elapsed 85%CPU 

我的测量和测试是否正确? 你也可以复制它们吗? 如果有,是否有人知道http.client内部发生了http.client ,使它更快? 为什么处理时间有这么大的差异?

基于两者的分析,主要区别似乎是requests版本正在为每个请求执行DNS查找,而http.client版本只执行一次。

# http.client
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1974    0.541    0.000    0.541    0.000 {method 'recv_into' of '_socket.socket' objects}
     1000    0.020    0.000    0.045    0.000 feedparser.py:470(_parse_headers)
    13000    0.015    0.000    0.563    0.000 {method 'readline' of '_io.BufferedReader' objects}
...

# requests
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1481    0.827    0.001    0.827    0.001 {method 'recv_into' of '_socket.socket' objects}
     1000    0.377    0.000    0.382    0.000 {built-in method _socket.gethostbyname}
     1000    0.123    0.000    0.123    0.000 {built-in method _scproxy._get_proxy_settings}
     1000    0.111    0.000    0.111    0.000 {built-in method _scproxy._get_proxies}
    92000    0.068    0.000    0.284    0.000 _collections_abc.py:675(__iter__)
...

您将主机名提供给http.client.HTTPConnection()一次,因此有意义的是它会调用gethostbyname一次。 requests.Session可能会缓存主机名查找,但显然不会。

编辑:经过一些进一步的研究,这不仅仅是一个简单的缓存问题。 有一个函数可以确定是否绕过最终调用gethostbyname代理,无论实际请求本身如何。

来自@Lukasa的复制粘贴回复发布在这里

请求较慢的原因是因为它比httplib实际上更多。 httplib可以被认为是堆栈的底层:它执行套接字的低级争用。 请求是两层,并添加了诸如cookie,连接池,其他设置和各种有趣的东西之类的东西。 这必然会减慢速度。 我们只需要计算比httplib更多的东西。

您可以通过查看请求的cProfile结果来看到这一点:结果比httplib的结果更多。 高级库总是会出现这种情况:它们会增加更多开销,因为它们需要做更多的工作。

虽然我们可以看一下目标性能改进,但在所有情况下,调用堆栈的绝对高度都会严重损害我们的性能。 这意味着“请求比httplib慢”的抱怨总是如此:它就像抱怨“请求比在套接字上发送精心设计的原始字节要慢”。 这是真的,而且永远都是真的:我们无能为力。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM