是否有更快的方式在Go中发出GET请求?

时间:2016-09-22 23:35:32

标签: 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()

    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()

仿形

我对此进行了相当多的研究。以下是我采取的一些方法:

  1. io.Copy
  2. 中使用不同的缓冲区大小
  3. 使用其他读者/作家
  4. 并发/并行
  5. 下载较大的文件
  6. 不同的缓冲区大小

    我使用io.CopyBuffer尝试了许多不同的缓冲区大小,我发现32KB的默认缓冲区大小让我的速度最快(比wget和Python的reqeusts慢了1.6到1.8倍。 {1}})。

    其他读者/作家

    所有其他读者和作者都比使用io.Copy慢得多。我尝试使用(f *File) Write和其他一些缓冲的读者/作者。

    并发/并行

    我甚至编写了一个相当长的程序,在标题中使用range并行下载此文件,但正如预期的那样,我似乎没有任何显着的速度提升。

    更大的文件

    我下载的文件是这个文件的三倍以上,而我的Go实现仍然比wget和请求慢1.5到2倍。

    其他注意事项

    1. 我在计算任何东西之前正在构建一个二进制文件。
    2. 绝大部分时间花在实际写作/复制response.Body上。无论我下载的文件有多大,该部分似乎都会占用大约0.3秒的经过时间。
    3. 那么我做错了什么?我是否应该期待GET请求在Go中花费更长时间?

1 个答案:

答案 0 :(得分:3)

我不知道该告诉你什么。我只是试图复制你的发现,但对我来说,所有3个版本花费大致相同的时间

wget   8.035s  
go     8.174s
python 8.242s

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