我通过编写一个客户端(以Web服务器的形式)来测试Go中的并发性,该客户端向Web服务器发出许多请求,然后返回发出这些请求所需的时间。基本上是一个基准工具。
以下是我目前正在使用的代码:main.go
我知道我的代码有很多缺陷,但我现在关注的是,如果我添加更多的常规调用,需要花多少精力来测试性能如何变化。在 CallSync 函数中,我必须继续添加到这个庞大的select语句以及启动go例程的func的大量调用列表中。我知道必须有更好的方法。我可能甚至不需要像现在这样同步,但如果我做了,我怎么能以更灵活的方式做到这一点?我希望有代码,我可以指定要调用的“go例程”的数量,它将调用该例程多次并与所有相关通道同步,而不必硬编码。
答案 0 :(得分:2)
像@JiangYD建议的那样,使用一个频道更容易:
type resp struct {
id string
i int
}
func Async(url string, c chan<- resp, id string, count int) {
cnt := 0
for i := 0; i < count; i++ {
GetPage(url)
cnt = cnt + 1
if cnt == 50 {
c <- resp{id, i}
cnt = 0
}
}
}
func CallSync(w http.ResponseWriter, r *http.Request) {
t0 := time.Now()
ch := make(chan resp, 20)
for i := range [20]struct{}{} {
go Async("http://localhost:8080/", ch, fmt.Sprintf("ch%02d", i), 2000)
}
count := 0
for count < 4000 {
select {
case r := <-ch:
fmt.Printf("%+v\n", r)
default:
}
}
t1 := time.Now()
diff := t1.Sub(t0)
num := diff.Nanoseconds() / int64(time.Millisecond)
msec := float64(num) / 1000
reqsec := float64(count) / msec
fmt.Fprintf(w, "%v requests\n", count)
fmt.Fprintf(w, "Performed in %v\n", diff)
fmt.Fprintf(w, "At a rate of %v (requests/sec)\n", reqsec)
}
另一种方法是使用reflect.Select
但这只会减慢速度。