我正在尝试编写一个基本上将流式CSV基准测试到HTTP端点的功能。
为此,我想生成数据并发布该数据。
然而,go
的数据竞争检测器表示存在数据竞争,并且基准测试的结束速度比我认为合理的速度快,所以我猜错了HTTP请求。
我应该如何构建我的测试代码以避免这种情况?
是否有办法等待HTTP客户端调用处理完毕?
func BenchmarkStream(b *testing.B) {
header := "header\n"
buf := bytes.NewBufferString(header)
var wg sync.WaitGroup
wg.Add(1)
go func() {
for i := 0; i < b.N; i++ {
buf.WriteString(fmt.Sprintf("%d\n", i+1))
}
wg.Done()
}() <-- this line is mentioned in the data race detector
w := httptest.NewRecorder()
r, _ := http.NewRequest("POST", "/", buf)
h := &MyHandler{}
h.ServeHTTP(w, r)
wg.Wait()
if w.Code != 200 {
b.Errorf("test failed")
}
}
编辑:@Grzegorz之前的评论让我质疑我的方法开始,我用io.Pipe
重构了它:
func BenchmarkStream(b *testing.B) {
pr, pw := io.Pipe()
go func() {
pw.Write([]byte("header\n"))
for i := 0; i < b.N; i++ {
pw.Write([]byte(fmt.Sprintf("%d\n", i+1)))
}
}()
w := httptest.NewRecorder()
r, _ := http.NewRequest("POST", "/", pr)
h := &MyHandler{}
h.ServeHTTP(w, r)
if w.Code != 200 {
b.Errorf("test failed")
}
}
答案 0 :(得分:1)
您正在两个goroutines之间共享buf
。
答案 1 :(得分:1)
如果您只调用一次处理程序,那么您将无法获得有用的基准测试结果。构建一次请求体,然后一遍又一遍地调用处理程序。
buf := &bytes.Buffer{}
buf.WriteString("header\n")
buf.WriteString(strings.Repeat("1\n", 1000)
body := buf.Bytes()
b.ResetTimer()
for i := 0; i < b.N; i++ {
w := httptest.NewRecorder()
r, err := http.NewRequest("POST", "/", bytes.NewReader(body))
if err != nil {
b.Fatal(err)
}
h := &MyHandler{}
h.ServeHTTP(w, r)
if w.Code != 200 {
b.Errorf("test failed")
}
}