diff --git a/buffer.go b/buffer.go index cdc92ff..804d775 100644 --- a/buffer.go +++ b/buffer.go @@ -2,9 +2,6 @@ package render import "bytes" -// bufPool represents a reusable buffer pool for executing templates into. -var bufPool *BufferPool - // BufferPool implements a pool of bytes.Buffers in the form of a bounded channel. // Pulled from the github.com/oxtoacart/bpool package (Apache licensed). type BufferPool struct { @@ -39,8 +36,3 @@ func (bp *BufferPool) Put(b *bytes.Buffer) { default: // Discard the buffer if the pool is full. } } - -// Initialize buffer pool for writing templates into. -func init() { - bufPool = NewBufferPool(64) -} diff --git a/engine.go b/engine.go index cdf1a1b..283a377 100644 --- a/engine.go +++ b/engine.go @@ -30,6 +30,8 @@ type HTML struct { Head Name string Templates *template.Template + + bp GenericBufferPool } // JSON built-in renderer. @@ -82,9 +84,14 @@ func (d Data) Render(w io.Writer, v interface{}) error { // Render a HTML response. func (h HTML) Render(w io.Writer, binding interface{}) error { - // Retrieve a buffer from the pool to write to. - out := bufPool.Get() - err := h.Templates.ExecuteTemplate(out, h.Name, binding) + var buf *bytes.Buffer + if h.bp != nil { + // If we have a bufferpool, allocate from it + buf = h.bp.Get() + defer h.bp.Put(buf) + } + + err := h.Templates.ExecuteTemplate(buf, h.Name, binding) if err != nil { return err } @@ -92,10 +99,8 @@ func (h HTML) Render(w io.Writer, binding interface{}) error { if hw, ok := w.(http.ResponseWriter); ok { h.Head.Write(hw) } - out.WriteTo(w) + buf.WriteTo(w) - // Return the buffer to the pool. - bufPool.Put(out) return nil } diff --git a/genericbufferpool.go b/genericbufferpool.go new file mode 100644 index 0000000..7e8d342 --- /dev/null +++ b/genericbufferpool.go @@ -0,0 +1,9 @@ +package render + +import "bytes" + +// GenericBufferPool abstracts buffer pool implementations +type GenericBufferPool interface { + Get() *bytes.Buffer + Put(*bytes.Buffer) +} diff --git a/render.go b/render.go index 3259f62..4cd11cd 100644 --- a/render.go +++ b/render.go @@ -103,6 +103,10 @@ type Options struct { // Enables using partials without the current filename suffix which allows use of the same template in multiple files. e.g {{ partial "carosuel" }} inside the home template will match carosel-home or carosel. // ***NOTE*** - This option should be named RenderPartialsWithoutSuffix as that is what it does. "Prefix" is a typo. Maintaining the existing name for backwards compatibility. RenderPartialsWithoutPrefix bool + + // BufferPool to use when rendering HTML templates. If none is supplied + // defaults to SizedBufferPool of size 32 with 512KiB buffers. + BufferPool GenericBufferPool } // HTMLOptions is a struct for overriding some rendering Options for specific HTML call. @@ -176,6 +180,10 @@ func (r *Render) prepareOptions() { if len(r.opt.XMLContentType) == 0 { r.opt.XMLContentType = ContentXML } + if r.opt.BufferPool == nil { + // 32 buffers of size 512KiB each + r.opt.BufferPool = NewSizedBufferPool(32, 1<<19) + } } func (r *Render) compileTemplates() { @@ -410,6 +418,7 @@ func (r *Render) HTML(w io.Writer, status int, name string, binding interface{}, Head: head, Name: name, Templates: r.templates, + bp: r.opt.BufferPool, } return r.Render(w, h, binding) diff --git a/render_html_test.go b/render_html_test.go index 0a0c0c6..f1c4c6b 100644 --- a/render_html_test.go +++ b/render_html_test.go @@ -1,6 +1,7 @@ package render import ( + "bytes" "errors" "html/template" "net/http" @@ -67,6 +68,38 @@ func TestHTMLBasic(t *testing.T) { expect(t, res.Body.String(), "