From 8ca66d3de8e812e79f37fcfa1331c9d2b4dc1b79 Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Wed, 22 Jun 2016 20:32:00 +0300 Subject: [PATCH] Use github.com/valyala/bytebufferpool, which should protect against memory fragmentation in the pool of byte buffers like mentioned in the PR #102 --- bytebuffer.go | 50 +++++++++++--------------------------------------- http.go | 21 ++++++++------------- 2 files changed, 19 insertions(+), 52 deletions(-) diff --git a/bytebuffer.go b/bytebuffer.go index 266f263..391782c 100644 --- a/bytebuffer.go +++ b/bytebuffer.go @@ -1,11 +1,7 @@ package fasthttp import ( - "sync" -) - -const ( - defaultByteBufferSize = 128 + "github.com/valyala/bytebufferpool" ) // ByteBuffer provides byte buffer, which can be used with fasthttp API @@ -15,38 +11,31 @@ const ( // slice. See example code for details. // // Use AcquireByteBuffer for obtaining an empty byte buffer. -type ByteBuffer struct { - - // B is a byte buffer to use in append-like workloads. - // See example code for details. - B []byte -} +type ByteBuffer bytebufferpool.ByteBuffer // Write implements io.Writer - it appends p to ByteBuffer.B func (b *ByteBuffer) Write(p []byte) (int, error) { - b.B = append(b.B, p...) - return len(p), nil + return bb(b).Write(p) } // WriteString appends s to ByteBuffer.B func (b *ByteBuffer) WriteString(s string) (int, error) { - b.B = append(b.B, s...) - return len(s), nil + return bb(b).WriteString(s) } // Set sets ByteBuffer.B to p func (b *ByteBuffer) Set(p []byte) { - b.B = append(b.B[:0], p...) + bb(b).Set(p) } // SetString sets ByteBuffer.B to s func (b *ByteBuffer) SetString(s string) { - b.B = append(b.B[:0], s...) + bb(b).SetString(s) } // Reset makes ByteBuffer.B empty. func (b *ByteBuffer) Reset() { - b.B = b.B[:0] + bb(b).Reset() } // AcquireByteBuffer returns an empty byte buffer from the pool. @@ -55,7 +44,7 @@ func (b *ByteBuffer) Reset() { // This reduces the number of memory allocations required for byte buffer // management. func AcquireByteBuffer() *ByteBuffer { - return defaultByteBufferPool.Acquire() + return (*ByteBuffer)(bytebufferpool.AcquireByteBuffer()) } // ReleaseByteBuffer returns byte buffer to the pool. @@ -63,26 +52,9 @@ func AcquireByteBuffer() *ByteBuffer { // ByteBuffer.B mustn't be touched after returning it to the pool. // Otherwise data races occur. func ReleaseByteBuffer(b *ByteBuffer) { - defaultByteBufferPool.Release(b) + bytebufferpool.ReleaseByteBuffer(bb(b)) } -type byteBufferPool struct { - pool sync.Pool -} - -var defaultByteBufferPool byteBufferPool - -func (p *byteBufferPool) Acquire() *ByteBuffer { - v := p.pool.Get() - if v == nil { - return &ByteBuffer{ - B: make([]byte, 0, defaultByteBufferSize), - } - } - return v.(*ByteBuffer) -} - -func (p *byteBufferPool) Release(b *ByteBuffer) { - b.B = b.B[:0] - p.pool.Put(b) +func bb(b *ByteBuffer) *bytebufferpool.ByteBuffer { + return (*bytebufferpool.ByteBuffer)(b) } diff --git a/http.go b/http.go index 37e3bad..1ddc0f3 100644 --- a/http.go +++ b/http.go @@ -304,23 +304,18 @@ func (req *Request) bodyBytes() []byte { func (resp *Response) bodyBuffer() *ByteBuffer { if resp.body == nil { - resp.body = responseBodyPool.Acquire() + resp.body = AcquireByteBuffer() } return resp.body } func (req *Request) bodyBuffer() *ByteBuffer { if req.body == nil { - req.body = requestBodyPool.Acquire() + req.body = AcquireByteBuffer() } return req.body } -var ( - requestBodyPool byteBufferPool - responseBodyPool byteBufferPool -) - // BodyGunzip returns un-gzipped body data. // // This method may be used if the request header contains @@ -435,7 +430,7 @@ func (resp *Response) ResetBody() { if resp.keepBodyBuffer { resp.body.Reset() } else { - responseBodyPool.Release(resp.body) + ReleaseByteBuffer(resp.body) resp.body = nil } } @@ -516,7 +511,7 @@ func (req *Request) ResetBody() { req.RemoveMultipartFormFiles() req.closeBodyStream() if req.body != nil { - requestBodyPool.Release(req.body) + ReleaseByteBuffer(req.body) req.body = nil } } @@ -1129,7 +1124,7 @@ func (resp *Response) gzipBody(level int) error { } }) } else { - w := responseBodyPool.Acquire() + w := AcquireByteBuffer() zw := acquireGzipWriter(w, level) _, err := zw.Write(resp.bodyBytes()) releaseGzipWriter(zw) @@ -1138,7 +1133,7 @@ func (resp *Response) gzipBody(level int) error { } // Hack: swap resp.body with w. - responseBodyPool.Release(resp.body) + ReleaseByteBuffer(resp.body) resp.body = w } resp.Header.SetCanonical(strContentEncoding, strGzip) @@ -1159,7 +1154,7 @@ func (resp *Response) deflateBody(level int) error { } }) } else { - w := responseBodyPool.Acquire() + w := AcquireByteBuffer() zw := acquireFlateWriter(w, level) _, err := zw.Write(resp.bodyBytes()) releaseFlateWriter(zw) @@ -1168,7 +1163,7 @@ func (resp *Response) deflateBody(level int) error { } // Hack: swap resp.body with w. - responseBodyPool.Release(resp.body) + ReleaseByteBuffer(resp.body) resp.body = w } resp.Header.SetCanonical(strContentEncoding, strDeflate)