]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: remove two more server allocations per-request
authorBrad Fitzpatrick <bradfitz@golang.org>
Thu, 28 Mar 2013 20:07:14 +0000 (13:07 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 28 Mar 2013 20:07:14 +0000 (13:07 -0700)
benchmark                                   old ns/op    new ns/op    delta
BenchmarkServerFakeConnWithKeepAliveLite        11031        10689   -3.10%

benchmark                                  old allocs   new allocs    delta
BenchmarkServerFakeConnWithKeepAliveLite           23           21   -8.70%

benchmark                                   old bytes    new bytes    delta
BenchmarkServerFakeConnWithKeepAliveLite         1668         1626   -2.52%

R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/8110044

src/pkg/net/http/server.go

index c38c4c8e1576e244eb6f0d9e848b32e379d4df93..3a0cca7fdc7c4dafa7034b21edc4aeeb213f531d 100644 (file)
@@ -763,8 +763,40 @@ func (cw *chunkWriter) writeHeader(p []byte) {
                cw.header.Set("Connection", "close")
        }
 
+       io.WriteString(w.conn.buf, statusLine(w.req, code))
+       cw.header.Write(w.conn.buf)
+       w.conn.buf.Write(crlf)
+}
+
+// statusLines is a cache of Status-Line strings, keyed by code (for
+// HTTP/1.1) or negative code (for HTTP/1.0). This is faster than a
+// map keyed by struct of two fields. This map's max size is bounded
+// by 2*len(statusText), two protocol types for each known official
+// status code in the statusText map.
+var (
+       statusMu    sync.RWMutex
+       statusLines = make(map[int]string)
+)
+
+// statusLine returns a response Status-Line (RFC 2616 Section 6.1)
+// for the given request and response status code.
+func statusLine(req *Request, code int) string {
+       // Fast path:
+       key := code
+       proto11 := req.ProtoAtLeast(1, 1)
+       if !proto11 {
+               key = -key
+       }
+       statusMu.RLock()
+       line, ok := statusLines[key]
+       statusMu.RUnlock()
+       if ok {
+               return line
+       }
+
+       // Slow path:
        proto := "HTTP/1.0"
-       if w.req.ProtoAtLeast(1, 1) {
+       if proto11 {
                proto = "HTTP/1.1"
        }
        codestring := strconv.Itoa(code)
@@ -772,9 +804,13 @@ func (cw *chunkWriter) writeHeader(p []byte) {
        if !ok {
                text = "status code " + codestring
        }
-       io.WriteString(w.conn.buf, proto+" "+codestring+" "+text+"\r\n")
-       cw.header.Write(w.conn.buf)
-       w.conn.buf.Write(crlf)
+       line = proto + " " + codestring + " " + text + "\r\n"
+       if ok {
+               statusMu.Lock()
+               defer statusMu.Unlock()
+               statusLines[key] = line
+       }
+       return line
 }
 
 // bodyAllowed returns true if a Write is allowed for this response type.