簡體   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