Commit a66aa77c authored by Dmitry Vyukov's avatar Dmitry Vyukov

net/http: add client benchmark

BenchmarkClient is intended for profiling
the client without the HTTP server code.
The server code runs in a subprocess.

Change-Id: I9aa128604d0d4e94dc5c0372dc86f962282ed6e8
Reviewed-on: https://go-review.googlesource.com/3164Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 3a523386
......@@ -2891,7 +2891,7 @@ func BenchmarkServer(b *testing.B) {
defer ts.Close()
b.StartTimer()
cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkServer")
cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkServer$")
cmd.Env = append([]string{
fmt.Sprintf("TEST_BENCH_CLIENT_N=%d", b.N),
fmt.Sprintf("TEST_BENCH_SERVER_URL=%s", ts.URL),
......@@ -2902,6 +2902,83 @@ func BenchmarkServer(b *testing.B) {
}
}
// A benchmark for profiling the client without the HTTP server code.
// The server code runs in a subprocess.
func BenchmarkClient(b *testing.B) {
b.ReportAllocs()
b.StopTimer()
port := os.Getenv("TEST_BENCH_SERVER_PORT") // can be set by user
if port == "" {
port = "39207"
}
var data = []byte("Hello world.\n")
if server := os.Getenv("TEST_BENCH_SERVER"); server != "" {
// Server process mode.
HandleFunc("/", func(w ResponseWriter, r *Request) {
r.ParseForm()
if r.Form.Get("stop") != "" {
os.Exit(0)
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write(data)
})
log.Fatal(ListenAndServe(":"+port, nil))
}
// Start server process.
cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkClient$")
cmd.Env = append(os.Environ(), "TEST_BENCH_SERVER=yes")
if err := cmd.Start(); err != nil {
b.Fatalf("subprocess failed to start: %v", err)
}
defer cmd.Process.Kill()
done := make(chan error)
go func() {
done <- cmd.Wait()
}()
// Wait for the server process to respond.
url := "http://localhost:" + port + "/"
for i := 0; i < 100; i++ {
time.Sleep(50 * time.Millisecond)
if _, err := Get(url); err == nil {
break
}
if i == 99 {
b.Fatalf("subprocess does not respond")
}
}
// Do b.N requests to the server.
b.StartTimer()
for i := 0; i < b.N; i++ {
res, err := Get(url)
if err != nil {
b.Fatalf("Get: %v", err)
}
body, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
b.Fatalf("ReadAll: %v", err)
}
if bytes.Compare(body, data) != 0 {
b.Fatalf("Got body: %q", body)
}
}
b.StopTimer()
// Instruct server process to stop.
Get(url + "?stop=yes")
select {
case err := <-done:
if err != nil {
b.Fatalf("subprocess failed: %v", err)
}
case <-time.After(5 * time.Second):
b.Fatalf("subprocess did not stop")
}
}
func BenchmarkServerFakeConnNoKeepAlive(b *testing.B) {
b.ReportAllocs()
req := reqBytes(`GET / HTTP/1.0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment