V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hujianxin
V2EX  ›  程序员

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

  •  
  •   hujianxin · 2019-03-23 15:54:12 +08:00 · 1495 次点击
    这是一个创建于 2072 天前的主题,其中的信息可能已经有所发展或是发生改变。

    服务器端程序( 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 程序错在哪里?

    第 1 条附言  ·  2019-03-23 21:42:25 +08:00
    看起来并不是 GIL 的事情啊,我是用 thread 原生写了一下,也是跟 go 版本一个级别的

    ```
    import requests
    from queue import Queue
    from threading import Thread


    class RunThread(Thread):
    def __init__(self, task_name, queue):
    super(RunThread, self).__init__(name=task_name)
    self.task_name = task_name
    self.queue = queue

    def run(self):
    resp = requests.get("http://localhost:8080")
    self.queue.put(f"{self.task_name}-{resp.content}")


    if __name__ == "__main__":
    threads = []
    q = Queue()
    for i in range(40):
    RunThread(f"task-{i}", q).start()

    i = 0
    while i < 40:
    if q.empty():
    continue
    r = q.get()
    print(r)
    i += 1
    ```

    `python thread-pyclient.py 3.91s user 0.16s system 86% cpu 4.678 total`
    baojiweicn2
        1
    baojiweicn2  
       2019-03-23 16:03:31 +08:00 via Android
    能不能用 aiohttp 加上 await 而不是线程试一下
    676529483
        2
    676529483  
       2019-03-23 16:14:38 +08:00
    python 你 socket 连接没有复用啊,应该先 session=request.Session()创建会话,再用 session.get()去请求
    再说 go 用的协程哎,python 改下 aiohttp+async 试下
    ipwx
        3
    ipwx  
       2019-03-23 16:28:28 +08:00
    Python 没有高效的多线程,因为 GIL。。。
    hujianxin
        4
    hujianxin  
    OP
       2019-03-23 21:20:40 +08:00
    aio 确实可以在这个 case 中达到 go 的效率,但是 python 世界中大多数操作都是不支持 async 的,比如我想使用 s3 的 python sdk 来操作 s3,这个就办不了了。。。
    hujianxin
        5
    hujianxin  
    OP
       2019-03-23 23:07:26 +08:00
    原因是我 python 只用了 5 个线程,我错了,此贴终结
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1363 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 17:35 · PVG 01:35 · LAX 09:35 · JFK 12:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.