Add a POST benchmark. Notably to show all the garbage from the body buffer.
For reference, where we're currently at:
$ go test -v -run=^$ -bench=. -benchtime=2s
PASS
BenchmarkServerGets 5000 527516 ns/op 1559 B/op 48 allocs/op
BenchmarkServerPosts 3000 747704 ns/op 69146 B/op 66 allocs/op
diff --git a/server_test.go b/server_test.go
index 7e3eca1..ef8b6e6 100644
--- a/server_test.go
+++ b/server_test.go
@@ -202,7 +202,12 @@
// multiple pairs for keys (e.g. "cookie"). The :method, :path, and
// :scheme headers default to GET, / and https.
func (st *serverTester) encodeHeader(headers ...string) []byte {
+ if len(headers)%2 == 1 {
+ panic("odd number of kv args")
+ }
+
st.headerBuf.Reset()
+
if len(headers) == 0 {
// Fast path, mostly for benchmarks, so test code doesn't pollute
// profiles when we're looking to improve server allocations.
@@ -212,10 +217,15 @@
return st.headerBuf.Bytes()
}
- pseudoCount := map[string]int{}
- if len(headers)%2 == 1 {
- panic("odd number of kv args")
+ if len(headers) == 2 && headers[0] == ":method" {
+ // Another fast path for benchmarks.
+ st.encodeHeaderField(":method", headers[1])
+ st.encodeHeaderField(":path", "/")
+ st.encodeHeaderField(":scheme", "https")
+ return st.headerBuf.Bytes()
}
+
+ pseudoCount := map[string]int{}
keys := []string{":method", ":path", ":scheme"}
vals := map[string][]string{
":method": {"GET"},
@@ -2175,3 +2185,35 @@
}
}
}
+
+func BenchmarkServerPosts(b *testing.B) {
+ b.ReportAllocs()
+
+ const msg = "Hello, world"
+ st := newServerTester(b, func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, msg)
+ })
+ defer st.Close()
+ st.greet()
+
+ // Give the server quota to reply. (plus it has the the 64KB)
+ if err := st.fr.WriteWindowUpdate(0, uint32(b.N*len(msg))); err != nil {
+ b.Fatal(err)
+ }
+
+ for i := 0; i < b.N; i++ {
+ id := 1 + uint32(i)*2
+ st.writeHeaders(HeadersFrameParam{
+ StreamID: id,
+ BlockFragment: st.encodeHeader(":method", "POST"),
+ EndStream: false,
+ EndHeaders: true,
+ })
+ st.writeData(id, true, nil)
+ st.wantHeaders()
+ df := st.wantData()
+ if !df.StreamEnded() {
+ b.Fatalf("DATA didn't have END_STREAM; got %v", df)
+ }
+ }
+}