Python 有没有更快的方法在Go中发出GET请求?

Python 有没有更快的方法在Go中发出GET请求?,python,http,go,wget,Python,Http,Go,Wget,考虑一下这个计划: package main import ( "net/http" "os" ) var url = "https://upload.wikimedia.org/wikipedia/commons/f/fe/FlumeRide%2C_Liseberg_-_last_steep_POV.ogv" func main() { response, _ := http.Get(url) defer response.Body.Close()

考虑一下这个计划:

package main

import (
    "net/http"
    "os"
)

var url = "https://upload.wikimedia.org/wikipedia/commons/f/fe/FlumeRide%2C_Liseberg_-_last_steep_POV.ogv"

func main() {
    response, _ := http.Get(url)
    defer response.Body.Close()

    f, _ := os.Create("output.ogv")
    defer f.Close()

    _, err = io.Copy(f, response.Body)
}
它的功能与
wget$url
相同,运行起来需要7.3秒(对我来说)
wget
只需~4.6秒。为什么会有如此巨大的差异?这个简单的Python程序在将整个视频写入磁盘之前将其加载到内存中,大约需要5.2秒

import requests

url = "https://upload.wikimedia.org/wikipedia/commons/f/fe/FlumeRide%2C_Liseberg_-_last_steep_POV.ogv"

def main():
    r = requests.get(url)
    with open('output.ogv','wb') as output:
        output.write(r.content)

if __name__ == "__main__":
    main()
轮廓 我对此做了不少调查。以下是我采取的一些方法:

  • 在io中使用不同的缓冲区大小。复制
  • 使用其他读者/作者
  • 并发/并行
  • 下载较大的文件
  • 不同的缓冲区大小 我使用
    io.CopyBuffer
    尝试了许多不同的缓冲区大小,发现默认的32KB缓冲区大小使我获得了最佳速度(仍然比
    wget
    和Python的
    Requests
    慢1.6到1.8倍)

    其他读者/作者 所有其他读者和作者的速度都比使用io.Copy慢得多,这是可以忽略的。我尝试使用
    (f*File)Write
    和一些其他缓冲读写器

    并发/并行 我甚至编写了一个相当长的程序,在头文件中使用
    range
    来并行下载这个文件,但正如预期的那样,我在速度上似乎没有任何显著的提高

    大文件 我下载了一个比这个文件大三倍多的文件,我的Go实现仍然比wget和请求慢1.5到2倍

    其他值得注意的事项
  • 在计时之前,我正在构建一个二进制文件
  • 绝大多数时间都花在实际编写/复制
    response.Body
    上。不管我下载的文件有多大,这个部分似乎只占了大约0.3秒的时间


  • 那么我做错了什么?我是否应该期望GET请求在Go中花费更长的时间?

    我不知道该告诉你什么。我只是想复制你的发现,但对我来说,这三个版本所用的时间大致相同

    wget   8.035s  
    go     8.174s
    python 8.242s
    

    也许在一个干净的VM或docker容器中尝试同样的实验?

    什么版本的go?你是否使用
    go run
    来执行程序?@MellowMarmot不,我在计时之前先构建一个二进制文件。@superfell我使用的是go版本1.7 darwin/AMD64,wget很可能使用gzip,但go没有。我认为你是对的。今晚我要在Arch上用Go 1.7试试这个。我会向你汇报情况的。有没有想过为什么Go 1.7 amd64/达尔文会这样做?我不确定。我在linux/amd64上用Go 1.7运行了测试。您可能想查看Go 1.7中引入的全新软件包。我自己还没有用过它,但它看起来正是调试它所需要的。