Go 同步发HTTP请求是不是要比Python慢很多?

imikay · 2018-07-03 19:31:19 · 2490 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2018-07-03 19:31:19 的主题,其中的信息可能已经有所发展或是发生改变。

Go 新手,最近想测试下用Go 发HTTP的速度,所以就写了个脚本测试了下,同时发两个请求,跟Python对比了下,发现慢了很多, Python 使用aiohttp耗时0.14s,Go版本的耗时 0.29s,慢了2倍

按理讲如果Go的速度不快的话,那至少也是跟Python差不多的嘛, 为什么会差这么多,是我写的方式不对吗?求指教。

Go 和 Python 代码如下:

import time
import aiohttp
import asyncio

async def fetch(session, url):
    async with session.post(url) as response:
        return await response.text()

async def main(url):
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, url)
        return html

if __name__ == '__main__':
    t = time.time()
    loop = asyncio.get_event_loop()
    urls = [
        "https://sina.com.cn", 
        "https://news.baidu.com"
    ]
    tasks = [main(url) for url in urls]
    responses = loop.run_until_complete(asyncio.gather(*tasks))

    for response in responses:
        print(response)

    print(time.time() - t)
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

func MakeRequest(client http.Client, url string, ch chan<- string) {
    reqest, _ := http.NewRequest("GET", url, nil)

    response, _ := client.Do(reqest)
    body, _ := ioutil.ReadAll(response.Body)
    ch <- string(body)
}

func main() {
    start := time.Now()
    urls := []string{"https://sina.com.cn", "https://news.baidu.com"}
    client := &http.Client{}
    ch := make(chan string)
    for _, url := range urls {
        go MakeRequest(*client, url, ch)
    }

    for range urls {
        fmt.Println(<-ch)
    }

    fmt.Printf("%.8fs elapsed\n", time.Since(start).Seconds())
}

有疑问加站长微信联系(非本文作者)

第 1 条附言  ·  2018-07-04 15:22:29

使用buffered channel,不过还是比Python慢

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

func MakeRequest(client http.Client, url string, ch chan<- string) {
    reqest, _ := http.NewRequest("GET", url, nil)

    response, _ := client.Do(reqest)
    body, _ := ioutil.ReadAll(response.Body)
    ch <- string(body)
}

func main() {
    start := time.Now()
    urls := []string{"https://sina.com.cn", "https://news.baidu.com"}
    client := &http.Client{}
    ch := make(chan string, len(urls))
    for _, url := range urls {
        go MakeRequest(*client, url, ch)
    }

    for range urls {
        fmt.Println(<-ch)
    }

    fmt.Printf("%.8fs elapsed\n", time.Since(start).Seconds())
}

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2490 次点击  
加入收藏 微博
19 回复  |  直到 2018-07-06 11:02:13
wwcd
wwcd · #1 · 7年之前

你python写的怎么是post方法,应该是get方法,我测试了一下修改为get后,python耗时2s+,go耗时0.2+,基本上耗时python是go的10倍

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()
imikay
imikay · #2 · 7年之前

哦,应该是get,我之前改来改去这个地方忘记改回去了,我再跑下试试

imikay
imikay · #3 · 7年之前

我重新跑了下,两个都差不多0.33s左右,奇怪,我之前测试两个都是Get和Post,Python几乎总是比Go快两倍。只不过我用的不是这两个网址。

imikay
imikay · #4 · 7年之前
wwcdwwcd #1 回复

你python写的怎么是`post`方法,应该是`get`方法,我测试了一下修改为`get`后,python耗时2s+,go耗时0.2+,基本上耗时python是go的10倍 ```python async def fetch(session, url): async with session.get(url) as response: return await response.text() ```

你的这个是跑了多次的效果吗,不应该有这个大差别的

imikay
imikay · #5 · 7年之前
wwcdwwcd #1 回复

你python写的怎么是`post`方法,应该是`get`方法,我测试了一下修改为`get`后,python耗时2s+,go耗时0.2+,基本上耗时python是go的10倍 ```python async def fetch(session, url): async with session.get(url) as response: return await response.text() ```

我这里本来有个用Python发请求的,我在想要不要换成Go的,这样看来其实没必要了。发请求主要还是跟网络有关,跟语言关系不大。

buscoop
buscoop · #6 · 7年之前

晕死,chan 为啥用unbuffered

wwcd
wwcd · #7 · 7年之前
imikayimikay #4 回复

#1楼 @wwcd 你的这个是跑了多次的效果吗,不应该有这个大差别的

我在阿里云服务器上跑了,跑了好几次的,你有没有检查你跑的输出结果是否一样啊?

imikay
imikay · #8 · 7年之前
buscoopbuscoop #6 回复

晕死,chan 为啥用unbuffered

我试下buffered chan,之前不太了解这个。

imikay
imikay · #9 · 7年之前
wwcdwwcd #7 回复

#4楼 @imikay 我在阿里云服务器上跑了,跑了好几次的,你有没有检查你跑的输出结果是否一样啊?

等我修改下再跑下试试

dosecin
dosecin · #10 · 7年之前

慢的不是go,是post方法

imikay
imikay · #11 · 7年之前
buscoopbuscoop #6 回复

晕死,chan 为啥用unbuffered

Buffered channel 是这么用的吧?试了下还是比Python慢了点

ch := make(chan string, len(urls))
imikay
imikay · #12 · 7年之前
dosecindosecin #10 回复

慢的不是go,是post方法

你的意思是HTTP请求慢的吗?

imikay
imikay · #13 · 7年之前
wwcdwwcd #7 回复

#4楼 @imikay 我在阿里云服务器上跑了,跑了好几次的,你有没有检查你跑的输出结果是否一样啊?

我检查过了,没啥问题啊,我是本机测试的。

wwcd
wwcd · #14 · 7年之前
imikayimikay #13 回复

#7楼 @wwcd 我检查过了,没啥问题啊,我是本机测试的。

不知道你的机器啥原因了。

(env3) root@zdevel ~/tmp # time python http_req.py > 1

real    0m2.938s
user    0m2.704s
sys     0m0.061s

(env3) root@zdevel ~/tmp # time go run http_req.go > 2

real    0m0.762s
user    0m0.581s
sys     0m0.167s
dingzewe
dingzewe · #15 · 7年之前

访问网页这种操作都是看自身网络状态的吧。。用什么语言都没用啊,还是看你实际网络访问哪家快。。谁就快啊。。

kumfo
kumfo · #16 · 7年之前
dingzewedingzewe #15 回复

访问网页这种操作都是看自身网络状态的吧。。用什么语言都没用啊,还是看你实际网络访问哪家快。。谁就快啊。。

我比较赞成这个观点

dosecin
dosecin · #17 · 7年之前
imikayimikay #12 回复

#10楼 @dosecin 你的意思是HTTP请求慢的吗?

你的代码本身时间消耗不在程序本身,而是网络请求。POST会在TCP3次握手后发请求,服务器确认后发请求数据,GET在TCP第3次握手时,跟随确认数据发送GET请求和数据,,所以GET会比POST少两次网络请求,速度上更快。

marlonche
marlonche · #18 · 7年之前

我觉得应该把用python和go发出的请求和收到的回复都打印出来:请求的header和body,回复的header和body, 然后比较两种语言发出的请求内容是否相同,回复内容是否相同, 如果完全相同,那就要通过pprof看下go的耗时在什么地方

linkerlin
linkerlin · #19 · 7年之前

启动速度的差异吧

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传