【发布时间】:2017-02-06 03:03:46
【问题描述】:
我做个测试看看select的表现,发现结果不是 好的。 go 版本是 1.7.3
package main
import (
"fmt"
"log"
"os"
"runtime/pprof"
"time"
)
var serverDone = make(chan struct{})
var serverDone1 = make(chan struct{})
var serverDone2 = make(chan struct{})
var serverDone3 = make(chan struct{})
var serverDone4 = make(chan struct{})
var serverDone5 = make(chan struct{})
func main() {
f, err := os.Create("cpu.pprof")
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
for i := 0; i < 1000; i++ {
go messageLoop()
}
<-time.After(10 * time.Second)
close(serverDone)
fmt.Println("finished")
}
func messageLoop() {
var ticker = time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
var counter = 0
for {
select {
case <-serverDone:
return
case <-serverDone1:
return
// case <-serverDone2:
// return
// case <-serverDone3:
// return
// case <-serverDone4:
// return
// case <-serverDone5:
// return
case <-ticker.C:
counter += 1
}
}
}
运行上述代码时,每次添加 serverDone 案例时,您会发现 CPU 会上升(在我的书中,大约 5%)。
当所有 serverDone 的情况都被移除时,CPU 大约是 5%,这并不好。
如果我将全局锁定的对象(如 serverDone)转到本地,性能会更好,但仍然不够好。
谁知道我的情况有什么问题,或者select语句的正确用法是什么?
【问题讨论】:
-
无法在我的 Linux 环境中重现,也许你应该编写你的操作系统。
-
@ymonad 你的 cpu 使用率是多少,你使用多少 serverDone 案例。我在一个centeros docker上测试过,结果一样
-
也许您可以详细说明困扰您的问题。您正在跨越 1000 个 goroutine,它们在 1 到 5 个通道上进行忙碌等待。您预计会发生什么,什么“性能”会是“好”,为什么?
-
@fwang2002 背后的原因是渠道实现。查看下面的答案
-
@Volker 因为 goroutine 切换,或者等待频道花费过多的 CPU 时间。 messageLoop 的典型用途是在网络处理程序中,它将创建一个包含 messageLoop 的对象实例,一个用于等待连接完成的通道,一个用于等待服务器关闭的通道,一个用于网络的通道消息,也许还有一个特定计时器的通道。如果最多 4 个通道,比在我的电脑中,它可能会花费 20% 的 CPU。而 1000 个 go 例程在网络应用程序中很常见。
标签: go