我在 Go 和 C++ 中对一个简单的套接字乒乓测试进行了基准测试。客户端首先向服务器发送 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 ./socketUnixClient
real 0m14.101s
user 0m5.242s
sys 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.out
real 0m8.690s
user 0m0.835s
sys 0m3.800s
代码文件
去服务器:
// socketUnixServer.go
package main
import (
"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.go
package main
import (
"log"
"net"
"encoding/binary"
)
const N = 1000000
func 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)
}
}
holdtom
相关分类