]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: add client benchmark
authorDmitry Vyukov <dvyukov@google.com>
Thu, 22 Jan 2015 19:54:18 +0000 (22:54 +0300)
committerDmitry Vyukov <dvyukov@google.com>
Tue, 27 Jan 2015 19:10:58 +0000 (19:10 +0000)
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/3164
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/net/http/serve_test.go

index eb695e2549dd35f8b6c7fcb7d6de4171e5dc1c0e..8086ef0800724b0601e30dc29cc449dbf7578f48 100644 (file)
@@ -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