这段程序我写的问题在哪呢?为什么 Python 比 Go 要慢?

2019-03-23 15:54:12 +08:00
 hujianxin

服务器端程序( python、go 分别去请求他)

package main

import (
	"log"
	"math/rand"
	"net/http"
	"time"
)

func hello(w http.ResponseWriter, r *http.Request) {
	time.Sleep(time.Second * time.Duration(rand.Intn(5)))
	w.Write([]byte("hello world"))
}

func main() {
	http.HandleFunc("/", hello)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
}

下面是比较的程序:

python 版本:

time python main.py 输出是 python main.py 0.37s user 0.13s system 3% cpu 16.545 total

import concurrent.futures
import requests


def do_run(task_name):
    resp = requests.get("http://localhost:8080")
    return f"{task_name}-{resp.content}"


if __name__ == "__main__":
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        futures = [executor.submit(do_run, f"task-{i}") for i in range(40)]
        for future in concurrent.futures.as_completed(futures):
            print(future.result())
        print("Done!")

go 版本:

time go run main.go 输出是: go run main.go 0.63s user 0.33s system 19% cpu 4.927 total

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"sync"
)

var httpClient http.Client

func init() {
	httpClient = *http.DefaultClient
}

func doRun(taskName string, taskChan chan string, wg *sync.WaitGroup) {
	resp, err := httpClient.Get("http://localhost:8080")
	if err != nil {
		taskChan <- "error"
		log.Fatal(err)
	}
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		taskChan <- "error"
		log.Fatalln(err)
	}
	taskChan <- fmt.Sprintf("%s--%s", taskName, string(b))
	wg.Done()
}

func main() {
	taskChan := make(chan string)
	wg := sync.WaitGroup{}
	go func() {
		wg.Add(40)
		wg.Wait()
        close(taskChan)
	}()

	for i := 0; i < 40; i++ {
		go doRun(fmt.Sprintf("task-%d", i), taskChan, &wg)
	}

	for r := range taskChan {
		fmt.Println(r)
	}
	fmt.Println("Done")
}

请教各位程序大佬看看我 python 程序错在哪里?

1507 次点击
所在节点    程序员
5 条回复
baojiweicn2
2019-03-23 16:03:31 +08:00
能不能用 aiohttp 加上 await 而不是线程试一下
676529483
2019-03-23 16:14:38 +08:00
python 你 socket 连接没有复用啊,应该先 session=request.Session()创建会话,再用 session.get()去请求
再说 go 用的协程哎,python 改下 aiohttp+async 试下
ipwx
2019-03-23 16:28:28 +08:00
Python 没有高效的多线程,因为 GIL。。。
hujianxin
2019-03-23 21:20:40 +08:00
aio 确实可以在这个 case 中达到 go 的效率,但是 python 世界中大多数操作都是不支持 async 的,比如我想使用 s3 的 python sdk 来操作 s3,这个就办不了了。。。
hujianxin
2019-03-23 23:07:26 +08:00
原因是我 python 只用了 5 个线程,我错了,此贴终结

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/547735

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX