Skip to content

Commit c908d9c

Browse files
authored
Refactor trailer Field for Improved Memory Efficiency and Performance (#1928)
* refact: represent trailer filed by [][]byte instead of []argsKV * fix: address golangci-lint warnings
1 parent 6371638 commit c908d9c

File tree

2 files changed

+63
-38
lines changed

2 files changed

+63
-38
lines changed

args.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -356,13 +356,6 @@ func visitArgs(args []argsKV, f func(k, v []byte)) {
356356
}
357357
}
358358

359-
func visitArgsKey(args []argsKV, f func(k []byte)) {
360-
for i, n := 0, len(args); i < n; i++ {
361-
kv := &args[i]
362-
f(kv.key)
363-
}
364-
}
365-
366359
func copyArgs(dst, src []argsKV) []argsKV {
367360
if cap(dst) < len(src) {
368361
tmp := make([]argsKV, len(src))

header.go

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ type ResponseHeader struct {
3434
contentEncoding []byte
3535
server []byte
3636
mulHeader [][]byte
37+
trailer [][]byte
3738

38-
h []argsKV
39-
trailer []argsKV
39+
h []argsKV
4040

4141
cookies []argsKV
4242
bufK []byte
@@ -72,9 +72,9 @@ type RequestHeader struct {
7272
contentType []byte
7373
userAgent []byte
7474
mulHeader [][]byte
75+
trailer [][]byte
7576

76-
h []argsKV
77-
trailer []argsKV
77+
h []argsKV
7878

7979
cookies []argsKV
8080

@@ -542,7 +542,14 @@ func (h *ResponseHeader) AddTrailerBytes(trailer []byte) error {
542542
}
543543
h.bufK = append(h.bufK[:0], key...)
544544
normalizeHeaderKey(h.bufK, h.disableNormalizing)
545-
h.trailer = appendArgBytes(h.trailer, h.bufK, nil, argsNoValue)
545+
if cap(h.trailer) > len(h.trailer) {
546+
h.trailer = h.trailer[:len(h.trailer)+1]
547+
h.trailer[len(h.trailer)-1] = append(h.trailer[len(h.trailer)-1][:0], h.bufK...)
548+
} else {
549+
key = make([]byte, len(h.bufK))
550+
copy(key, h.bufK)
551+
h.trailer = append(h.trailer, key)
552+
}
546553
}
547554

548555
return err
@@ -890,7 +897,14 @@ func (h *RequestHeader) AddTrailerBytes(trailer []byte) error {
890897
}
891898
h.bufK = append(h.bufK[:0], key...)
892899
normalizeHeaderKey(h.bufK, h.disableNormalizing)
893-
h.trailer = appendArgBytes(h.trailer, h.bufK, nil, argsNoValue)
900+
if cap(h.trailer) > len(h.trailer) {
901+
h.trailer = h.trailer[:len(h.trailer)+1]
902+
h.trailer[len(h.trailer)-1] = append(h.trailer[len(h.trailer)-1][:0], h.bufK...)
903+
} else {
904+
key = make([]byte, len(h.bufK))
905+
copy(key, h.bufK)
906+
h.trailer = append(h.trailer, key)
907+
}
894908
}
895909

896910
return err
@@ -1162,7 +1176,7 @@ func (h *ResponseHeader) CopyTo(dst *ResponseHeader) {
11621176
dst.server = append(dst.server, h.server...)
11631177
dst.h = copyArgs(dst.h, h.h)
11641178
dst.cookies = copyArgs(dst.cookies, h.cookies)
1165-
dst.trailer = copyArgs(dst.trailer, h.trailer)
1179+
dst.trailer = copyTrailer(dst.trailer, h.trailer)
11661180
}
11671181

11681182
// CopyTo copies all the headers to dst.
@@ -1182,7 +1196,7 @@ func (h *RequestHeader) CopyTo(dst *RequestHeader) {
11821196
dst.host = append(dst.host, h.host...)
11831197
dst.contentType = append(dst.contentType, h.contentType...)
11841198
dst.userAgent = append(dst.userAgent, h.userAgent...)
1185-
dst.trailer = append(dst.trailer, h.trailer...)
1199+
dst.trailer = copyTrailer(dst.trailer, h.trailer)
11861200
dst.h = copyArgs(dst.h, h.h)
11871201
dst.cookies = copyArgs(dst.cookies, h.cookies)
11881202
dst.cookiesCollected = h.cookiesCollected
@@ -1215,7 +1229,7 @@ func (h *ResponseHeader) VisitAll(f func(key, value []byte)) {
12151229
})
12161230
}
12171231
if len(h.trailer) > 0 {
1218-
f(strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
1232+
f(strTrailer, appendTrailerBytes(nil, h.trailer, strCommaSpace))
12191233
}
12201234
visitArgs(h.h, f)
12211235
if h.ConnectionClose() {
@@ -1227,14 +1241,18 @@ func (h *ResponseHeader) VisitAll(f func(key, value []byte)) {
12271241
//
12281242
// f must not retain references to value after returning.
12291243
func (h *ResponseHeader) VisitAllTrailer(f func(value []byte)) {
1230-
visitArgsKey(h.trailer, f)
1244+
for i := range h.trailer {
1245+
f(h.trailer[i])
1246+
}
12311247
}
12321248

12331249
// VisitAllTrailer calls f for each request Trailer.
12341250
//
12351251
// f must not retain references to value after returning.
12361252
func (h *RequestHeader) VisitAllTrailer(f func(value []byte)) {
1237-
visitArgsKey(h.trailer, f)
1253+
for i := range h.trailer {
1254+
f(h.trailer[i])
1255+
}
12381256
}
12391257

12401258
// VisitAllCookie calls f for each response cookie.
@@ -1279,7 +1297,7 @@ func (h *RequestHeader) VisitAll(f func(key, value []byte)) {
12791297
f(strUserAgent, userAgent)
12801298
}
12811299
if len(h.trailer) > 0 {
1282-
f(strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
1300+
f(strTrailer, appendTrailerBytes(nil, h.trailer, strCommaSpace))
12831301
}
12841302

12851303
h.collectCookies()
@@ -1925,7 +1943,7 @@ func (h *ResponseHeader) peek(key []byte) []byte {
19251943
case HeaderSetCookie:
19261944
return appendResponseCookieBytes(nil, h.cookies)
19271945
case HeaderTrailer:
1928-
return appendArgsKeyBytes(nil, h.trailer, strCommaSpace)
1946+
return appendTrailerBytes(nil, h.trailer, strCommaSpace)
19291947
default:
19301948
return peekArgBytes(h.h, key)
19311949
}
@@ -1952,7 +1970,7 @@ func (h *RequestHeader) peek(key []byte) []byte {
19521970
}
19531971
return peekArgBytes(h.h, key)
19541972
case HeaderTrailer:
1955-
return appendArgsKeyBytes(nil, h.trailer, strCommaSpace)
1973+
return appendTrailerBytes(nil, h.trailer, strCommaSpace)
19561974
default:
19571975
return peekArgBytes(h.h, key)
19581976
}
@@ -1999,7 +2017,7 @@ func (h *RequestHeader) peekAll(key []byte) [][]byte {
19992017
h.mulHeader = peekAllArgBytesToDst(h.mulHeader, h.h, key)
20002018
}
20012019
case HeaderTrailer:
2002-
h.mulHeader = append(h.mulHeader, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
2020+
h.mulHeader = append(h.mulHeader, appendTrailerBytes(nil, h.trailer, strCommaSpace))
20032021
default:
20042022
h.mulHeader = peekAllArgBytesToDst(h.mulHeader, h.h, key)
20052023
}
@@ -2043,7 +2061,7 @@ func (h *ResponseHeader) peekAll(key []byte) [][]byte {
20432061
case HeaderSetCookie:
20442062
h.mulHeader = append(h.mulHeader, appendResponseCookieBytes(nil, h.cookies))
20452063
case HeaderTrailer:
2046-
h.mulHeader = append(h.mulHeader, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
2064+
h.mulHeader = append(h.mulHeader, appendTrailerBytes(nil, h.trailer, strCommaSpace))
20472065
default:
20482066
h.mulHeader = peekAllArgBytesToDst(h.mulHeader, h.h, key)
20492067
}
@@ -2069,8 +2087,7 @@ func (h *RequestHeader) PeekKeys() [][]byte {
20692087
// Any future calls to the Peek* will modify the returned value.
20702088
// Do not store references to returned value. Make copies instead.
20712089
func (h *RequestHeader) PeekTrailerKeys() [][]byte {
2072-
h.mulHeader = h.mulHeader[:0]
2073-
h.mulHeader = peekArgsKeys(h.mulHeader, h.trailer)
2090+
h.mulHeader = copyTrailer(h.mulHeader, h.trailer)
20742091
return h.mulHeader
20752092
}
20762093

@@ -2094,7 +2111,9 @@ func (h *ResponseHeader) PeekKeys() [][]byte {
20942111
// Do not store references to returned value. Make copies instead.
20952112
func (h *ResponseHeader) PeekTrailerKeys() [][]byte {
20962113
h.mulHeader = h.mulHeader[:0]
2097-
h.mulHeader = peekArgsKeys(h.mulHeader, h.trailer)
2114+
for i, n := 0, len(h.trailer); i < n; i++ {
2115+
h.mulHeader = append(h.mulHeader, h.trailer[i])
2116+
}
20982117
return h.mulHeader
20992118
}
21002119

@@ -2462,8 +2481,8 @@ func (h *ResponseHeader) writeTrailer(w *bufio.Writer) error {
24622481
func (h *ResponseHeader) TrailerHeader() []byte {
24632482
h.bufV = h.bufV[:0]
24642483
for _, t := range h.trailer {
2465-
value := h.peek(t.key)
2466-
h.bufV = appendHeaderLine(h.bufV, t.key, value)
2484+
value := h.peek(t)
2485+
h.bufV = appendHeaderLine(h.bufV, t, value)
24672486
}
24682487
h.bufV = append(h.bufV, strCRLF...)
24692488
return h.bufV
@@ -2523,7 +2542,7 @@ func (h *ResponseHeader) AppendBytes(dst []byte) []byte {
25232542
// Exclude trailer from header
25242543
exclude := false
25252544
for _, t := range h.trailer {
2526-
if bytes.Equal(kv.key, t.key) {
2545+
if bytes.Equal(kv.key, t) {
25272546
exclude = true
25282547
break
25292548
}
@@ -2534,7 +2553,7 @@ func (h *ResponseHeader) AppendBytes(dst []byte) []byte {
25342553
}
25352554

25362555
if len(h.trailer) > 0 {
2537-
dst = appendHeaderLine(dst, strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
2556+
dst = appendHeaderLine(dst, strTrailer, appendTrailerBytes(nil, h.trailer, strCommaSpace))
25382557
}
25392558

25402559
n := len(h.cookies)
@@ -2594,8 +2613,8 @@ func (h *RequestHeader) writeTrailer(w *bufio.Writer) error {
25942613
func (h *RequestHeader) TrailerHeader() []byte {
25952614
h.bufV = h.bufV[:0]
25962615
for _, t := range h.trailer {
2597-
value := h.peek(t.key)
2598-
h.bufV = appendHeaderLine(h.bufV, t.key, value)
2616+
value := h.peek(t)
2617+
h.bufV = appendHeaderLine(h.bufV, t, value)
25992618
}
26002619
h.bufV = append(h.bufV, strCRLF...)
26012620
return h.bufV
@@ -2656,7 +2675,7 @@ func (h *RequestHeader) AppendBytes(dst []byte) []byte {
26562675
// Exclude trailer from header
26572676
exclude := false
26582677
for _, t := range h.trailer {
2659-
if bytes.Equal(kv.key, t.key) {
2678+
if bytes.Equal(kv.key, t) {
26602679
exclude = true
26612680
break
26622681
}
@@ -2667,7 +2686,7 @@ func (h *RequestHeader) AppendBytes(dst []byte) []byte {
26672686
}
26682687

26692688
if len(h.trailer) > 0 {
2670-
dst = appendHeaderLine(dst, strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
2689+
dst = appendHeaderLine(dst, strTrailer, appendTrailerBytes(nil, h.trailer, strCommaSpace))
26712690
}
26722691

26732692
// there is no need in h.collectCookies() here, since if cookies aren't collected yet,
@@ -3608,17 +3627,30 @@ func AppendNormalizedHeaderKeyBytes(dst, key []byte) []byte {
36083627
return AppendNormalizedHeaderKey(dst, b2s(key))
36093628
}
36103629

3611-
func appendArgsKeyBytes(dst []byte, args []argsKV, sep []byte) []byte {
3612-
for i, n := 0, len(args); i < n; i++ {
3613-
kv := &args[i]
3614-
dst = append(dst, kv.key...)
3630+
func appendTrailerBytes(dst []byte, trailer [][]byte, sep []byte) []byte {
3631+
for i, n := 0, len(trailer); i < n; i++ {
3632+
dst = append(dst, trailer[i]...)
36153633
if i+1 < n {
36163634
dst = append(dst, sep...)
36173635
}
36183636
}
36193637
return dst
36203638
}
36213639

3640+
func copyTrailer(dst, src [][]byte) [][]byte {
3641+
if cap(dst) > len(src) {
3642+
dst = dst[:len(src)]
3643+
} else {
3644+
dst = append(dst[:0], src...)
3645+
}
3646+
3647+
for i := range dst {
3648+
dst[i] = make([]byte, len(src[i]))
3649+
copy(dst[i], src[i])
3650+
}
3651+
return dst
3652+
}
3653+
36223654
var (
36233655
errNeedMore = errors.New("need more data: cannot find trailing lf")
36243656
errInvalidName = errors.New("invalid header name")

0 commit comments

Comments
 (0)