From 97577c07a57b2c9160d927825fbb01cb2912a46b Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Tue, 7 Nov 2017 21:37:35 -0300 Subject: [PATCH] Include a buffer pool to improve memory usage --- .../controller/template/buffer_pool.go | 51 +++++++++++++++++++ .../ingress/controller/template/template.go | 21 +++----- 2 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 internal/ingress/controller/template/buffer_pool.go diff --git a/internal/ingress/controller/template/buffer_pool.go b/internal/ingress/controller/template/buffer_pool.go new file mode 100644 index 000000000..e0a1f287c --- /dev/null +++ b/internal/ingress/controller/template/buffer_pool.go @@ -0,0 +1,51 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package template + +import ( + "bytes" + "sync" +) + +// BufferPool defines a Pool of Buffers +type BufferPool struct { + sync.Pool +} + +// NewBufferPool creates a new BufferPool with a custom buffer size +func NewBufferPool(s int) *BufferPool { + return &BufferPool{ + Pool: sync.Pool{ + New: func() interface{} { + b := bytes.NewBuffer(make([]byte, s)) + b.Reset() + return b + }, + }, + } +} + +// Get returns a Buffer from the pool +func (bp *BufferPool) Get() *bytes.Buffer { + return bp.Pool.Get().(*bytes.Buffer) +} + +// Put resets ans returns a Buffer to the pool +func (bp *BufferPool) Put(b *bytes.Buffer) { + b.Reset() + bp.Pool.Put(b) +} diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index 72de61cc2..078a05a0e 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -17,7 +17,6 @@ limitations under the License. package template import ( - "bytes" "encoding/base64" "encoding/json" "fmt" @@ -52,7 +51,7 @@ const ( type Template struct { tmpl *text_template.Template fw watch.FileWatcher - s int + bp *BufferPool } //NewTemplate returns a new Template instance or an @@ -70,7 +69,7 @@ func NewTemplate(file string, onChange func()) (*Template, error) { return &Template{ tmpl: tmpl, fw: fw, - s: defBufferSize, + bp: NewBufferPool(defBufferSize), }, nil } @@ -82,15 +81,11 @@ func (t *Template) Close() { // Write populates a buffer using a template with NGINX configuration // and the servers and upstreams created by Ingress rules func (t *Template) Write(conf config.TemplateConfig) ([]byte, error) { - tmplBuf := bytes.NewBuffer(make([]byte, 0, t.s)) - outCmdBuf := bytes.NewBuffer(make([]byte, 0, t.s)) + tmplBuf := t.bp.Get() + defer t.bp.Put(tmplBuf) - defer func() { - if t.s < tmplBuf.Cap() { - glog.V(2).Infof("adjusting template buffer size from %v to %v", t.s, tmplBuf.Cap()) - t.s = tmplBuf.Cap() - } - }() + outCmdBuf := t.bp.Get() + defer t.bp.Put(outCmdBuf) if glog.V(3) { b, err := json.Marshal(conf) @@ -115,9 +110,7 @@ func (t *Template) Write(conf config.TemplateConfig) ([]byte, error) { return tmplBuf.Bytes(), nil } - a := make([]byte, outCmdBuf.Len()) - copy(a, outCmdBuf.Bytes()) - return a, nil + return outCmdBuf.Bytes(), nil } var (