亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么 Go 套接字比 C++ 套接字慢?

為什么 Go 套接字比 C++ 套接字慢?

Go
揚帆大魚 2023-05-22 16:00:37
我在 Go 和 C++ 中對一個簡單的套接字乒乓測試進行了基準測試??蛻舳耸紫认蚍掌靼l送 0。服務器遞增它獲得的任何數字并將其發送回客戶端??蛻舳藢底只仫@給服務器,并在數字達到 1,000,000 時停止??蛻舳撕头掌鞫荚谕慌_計算機上,所以我在這兩種情況下都使用 Unix 套接字。(我還嘗試了同主機 TCP 套接字,顯示了類似的結果)。Go 測試需要 14 秒,而 C++ 測試需要 8 秒。這讓我感到驚訝,因為我已經運行了相當多的 Go 與 C++ 基準測試,并且通常只要我不觸發垃圾收集器,Go 的性能就與 C++ 一樣。我在 Mac 上,盡管評論者也報告說 Go 版本在 Linux 上運行速度較慢。想知道我是否缺少一種優化 Go 程序的方法,或者是否只是底層效率低下。下面是我運行的用于執行測試的命令以及測試結果。所有代碼文件都粘貼在這個問題的底部。運行圍棋服務器:$ rm /tmp/go.sock$ go run socketUnixServer.go運行 Go 客戶端:$ go build socketUnixClient.go; time ./socketUnixClientreal    0m14.101suser    0m5.242ssys     0m7.883s運行 C++ 服務器:$ rm /tmp/cpp.sock$ clang++ -std=c++11 tcpServerIncUnix.cpp -O3; ./a.out運行 C++ 客戶端:$ clang++ -std=c++11 tcpClientIncUnix.cpp -O3; time ./a.outreal    0m8.690suser    0m0.835ssys     0m3.800s代碼文件去服務器:// socketUnixServer.gopackage mainimport (    "log"    "net"    "encoding/binary")func main() {    ln, err := net.Listen("unix", "/tmp/go.sock")    if err != nil {        log.Fatal("Listen error: ", err)    }    c, err := ln.Accept()    if err != nil {        panic(err)    }    log.Println("Connected with client!")    readbuf := make([]byte, 4)    writebuf := make([]byte, 4)    for {        c.Read(readbuf)        clientNum := binary.BigEndian.Uint32(readbuf)        binary.BigEndian.PutUint32(writebuf, clientNum+1)        c.Write(writebuf)    }}去客戶端:// socketUnixClient.gopackage mainimport (    "log"    "net"    "encoding/binary")const N = 1000000func main() {    c, err := net.Dial("unix", "/tmp/go.sock")    if err != nil {        log.Fatal("Dial error", err)    }    defer c.Close()    readbuf := make([]byte, 4)    writebuf := make([]byte, 4)    var currNumber uint32 = 0    for currNumber < N {        binary.BigEndian.PutUint32(writebuf, currNumber)        c.Write(writebuf)        // Read the incremented number from server        c.Read(readbuf[:])        currNumber = binary.BigEndian.Uint32(readbuf)    }}
查看完整描述

1 回答

?
holdtom

TA貢獻1805條經驗 獲得超10個贊

首先,我確認這個問題中的 Go 程序確實比 C++ 程序運行得明顯慢。我認為知道原因確實很有趣。

我用 分析了 Go 客戶端和服務器,pprof發現這syscall.Syscall占用了總執行時間的 70%。根據這張票,在 Go 中系統調用比在 C 中慢大約 1.4 倍。

(pprof) top -cum

Showing nodes accounting for 18.78s, 67.97% of 27.63s total

Dropped 44 nodes (cum <= 0.14s)

Showing top 10 nodes out of 44

? flat? flat%? ?sum%? ? ? ? cum? ?cum%

?0.11s? ?0.4%? ?0.4%? ? ?22.65s 81.98%? main.main

? ? ?0? ? ?0%? ?0.4%? ? ?22.65s 81.98%? runtime.main

18.14s 65.65% 66.05%? ? ?19.91s 72.06%? syscall.Syscall

?0.03s? 0.11% 66.16%? ? ?12.91s 46.72%? net.(*conn).Read

?0.10s? 0.36% 66.52%? ? ?12.88s 46.62%? net.(*netFD).Read

?0.16s? 0.58% 67.10%? ? ?12.78s 46.25%? internal/poll.(*FD).Read

?0.06s? 0.22% 67.32%? ? ?11.87s 42.96%? syscall.Read

?0.11s? ?0.4% 67.72%? ? ?11.81s 42.74%? syscall.read

?0.02s 0.072% 67.79%? ? ? 9.30s 33.66%? net.(*conn).Write

?0.05s? 0.18% 67.97%? ? ? 9.28s 33.59%? net.(*netFD).Write

Conn.Write我逐漸減少和調用的次數Conn.Read并相應地增加緩沖區的大小,以便傳輸的字節數保持不變。結果是程序進行的這些調用越少,其性能就越接近 C++ 版本。


查看完整回答
反對 回復 2023-05-22
  • 1 回答
  • 0 關注
  • 158 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號