mirror of
https://github.com/golang/go.git
synced 2025-11-05 19:20:58 +00:00
net/http: remove two more server allocations per-request
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
This commit is contained in:
parent
04341b246e
commit
42a840860f
1 changed files with 40 additions and 4 deletions
|
|
@ -763,8 +763,40 @@ func (cw *chunkWriter) writeHeader(p []byte) {
|
||||||
cw.header.Set("Connection", "close")
|
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"
|
proto := "HTTP/1.0"
|
||||||
if w.req.ProtoAtLeast(1, 1) {
|
if proto11 {
|
||||||
proto = "HTTP/1.1"
|
proto = "HTTP/1.1"
|
||||||
}
|
}
|
||||||
codestring := strconv.Itoa(code)
|
codestring := strconv.Itoa(code)
|
||||||
|
|
@ -772,9 +804,13 @@ func (cw *chunkWriter) writeHeader(p []byte) {
|
||||||
if !ok {
|
if !ok {
|
||||||
text = "status code " + codestring
|
text = "status code " + codestring
|
||||||
}
|
}
|
||||||
io.WriteString(w.conn.buf, proto+" "+codestring+" "+text+"\r\n")
|
line = proto + " " + codestring + " " + text + "\r\n"
|
||||||
cw.header.Write(w.conn.buf)
|
if ok {
|
||||||
w.conn.buf.Write(crlf)
|
statusMu.Lock()
|
||||||
|
defer statusMu.Unlock()
|
||||||
|
statusLines[key] = line
|
||||||
|
}
|
||||||
|
return line
|
||||||
}
|
}
|
||||||
|
|
||||||
// bodyAllowed returns true if a Write is allowed for this response type.
|
// bodyAllowed returns true if a Write is allowed for this response type.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue