为什么 Python 的请求比 C 的 libcurl 快 10 倍?

éta*_*ogy 8 c python https curl libcurl

对于 1.6 MB 的请求(需要800 毫秒,而/有时需要多达7 秒),Python 的requests库似乎比 C 的库libcurl(C API、CLI 应用程序和 Python API)快 10 倍。requestscurllibcurl

  • 为什么是这样?

  • 我怎样才能curl在 C 中运行得像requests在 Python 中一样快?

libcurl似乎以 16KB 块的形式得到答复,而请求似乎一下子就得到了整个事情,但我不确定是不是这样......我试过了,curl_easy_setopt(curl_get, CURLOPT_BUFFERSIZE, 1<<19)但让缓冲区大小变小似乎只有好处。

我试着看源代码requests,而且我觉得它使用urllib3作为它的HTTP“后端” ......但使用urllib3直接在相同的(失望)导致的结果使用curl

这里有些例子。

/*
gcc-8 test.c -o test -lcurl  &&  t ./test
*/
#include <curl/curl.h>

int main(){
  CURLcode curl_st;
  curl_global_init(CURL_GLOBAL_ALL);

  CURL* curl_get = curl_easy_init();
  curl_easy_setopt(curl_get, CURLOPT_URL,           "https://api.binance.com/api/v3/exchangeInfo");
  curl_easy_setopt(curl_get, CURLOPT_BUFFERSIZE, 1<<19);
  curl_st=curl_easy_perform(curl_get);  if(curl_st!=CURLE_OK) printf("\x1b[91mFAIL  \x1b[37m%s\x1b[0m\n", curl_easy_strerror(curl_st));

  curl_easy_cleanup(curl_get);
  curl_global_cleanup();
}
Run Code Online (Sandbox Code Playgroud)
'''FAST'''
import requests
reply = requests.get('https://api.binance.com/api/v3/exchangeInfo')
print(reply.text)
Run Code Online (Sandbox Code Playgroud)
'''SLOW'''
import urllib3
pool = urllib3.PoolManager()  # conn = pool.connection_from_url('https://api.binance.com/api/v3/exchangeInfo')
reply = pool.request('GET', 'https://api.binance.com/api/v3/exchangeInfo')
print(reply.data)
print(len(reply.data))
Run Code Online (Sandbox Code Playgroud)
'''SLOW!'''
import urllib.request
with urllib.request.urlopen('https://api.binance.com/api/v3/exchangeInfo') as response:
  html = response.read()
Run Code Online (Sandbox Code Playgroud)
'''SLOW!'''
import pycurl
from io import BytesIO
buf  = BytesIO()
curl = pycurl.Curl()
curl.setopt(curl.URL, 'https://api.binance.com/api/v3/exchangeInfo')
curl.setopt(curl.WRITEDATA, buf)
curl.perform()
curl.close()
body = buf.getvalue()  # Body is a byte string. We have to know the encoding in order to print it to a text file such as standard output.
print(body.decode('iso-8859-1'))
Run Code Online (Sandbox Code Playgroud)
curl https://api.binance.com/api/v3/exchangeInfo
Run Code Online (Sandbox Code Playgroud)

squ*_*age 10

加快 Web 内容传输的一种方法是使用HTTP 压缩。这是通过在服务器和客户端之间发送数据之前即时压缩数据来实现的,因此传输时间更少。

尽管libcurl 支持 HTTP 压缩,但默认情况下它是禁用的:。从CURLOPT_ACCEPT_ENCODING文档:

将 CURLOPT_ACCEPT_ENCODING 设置为 NULL 以显式禁用它,这使得 libcurl 不会发送 Accept-Encoding: 标头并且不会自动解压缩接收到的内容。

这个参数的默认值是NULL,所以除非你专门启用了HTTP压缩,否则你不会得到它。