mirror of
https://github.com/golang/go
synced 2024-11-27 01:01:21 -07:00
net/textproto: do not buffer a line if we know the next line is empty
readContinuedLineSlice intends to buffer a continued line of text, where a continued line can continue through newlines so long as the next line begins with a space or tab. The current optimization is to not try to buffer and build a line if we immediately see that the next line begins with an ASCII character. This adds avoiding copying the line if we see that the next line is \n or \r\n as well. Notably, headers always end in \r\n\r\n. In the general, well formatted header case, we can now avoid ever allocating textproto.Reader's internal reusable buf. This can mildly be seen in net/http's BenchmarkClientServer: name old time/op new time/op delta ClientServer-4 66.4µs ± 0% 66.2µs ± 0% -0.35% (p=0.004 n=10+10) name old alloc/op new alloc/op delta ClientServer-4 4.87kB ± 0% 4.82kB ± 0% -1.01% (p=0.000 n=6+10) name old allocs/op new allocs/op delta ClientServer-4 64.0 ± 0% 63.0 ± 0% -1.56% (p=0.000 n=10+10) Change-Id: Id8c2ab69086ac481b90abda289396dcb7bfe8851 Reviewed-on: https://go-review.googlesource.com/c/134227 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
21d2e15ee1
commit
f5b695030b
@ -129,12 +129,13 @@ func (r *Reader) readContinuedLineSlice() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Optimistically assume that we have started to buffer the next line
|
// Optimistically assume that we have started to buffer the next line
|
||||||
// and it starts with an ASCII letter (the next header key), so we can
|
// and it starts with an ASCII letter (the next header key), or a blank
|
||||||
// avoid copying that buffered data around in memory and skipping over
|
// line, so we can avoid copying that buffered data around in memory
|
||||||
// non-existent whitespace.
|
// and skipping over non-existent whitespace.
|
||||||
if r.R.Buffered() > 1 {
|
if r.R.Buffered() > 1 {
|
||||||
peek, err := r.R.Peek(1)
|
peek, _ := r.R.Peek(2)
|
||||||
if err == nil && isASCIILetter(peek[0]) {
|
if len(peek) > 0 && (isASCIILetter(peek[0]) || peek[0] == '\n') ||
|
||||||
|
len(peek) == 2 && peek[0] == '\r' && peek[1] == '\n' {
|
||||||
return trim(line), nil
|
return trim(line), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user