Browse Source

Use sync.Pool to recycle gzip.Writer

gzip.Writer internally uses flate.Writer which allocates 1.4 MB memory
each time NewWriter is called. (see golang/go#6138)
By using a resource pool and reseting the writer we can reduce garbage collection a lot.
Daniel Heckrath 9 years ago
parent
commit
c695198c95
1 changed files with 14 additions and 4 deletions
  1. 14 4
      gzip.go

+ 14 - 4
gzip.go

@@ -2,9 +2,11 @@ package gzip
 
 
 import (
 import (
 	"compress/gzip"
 	"compress/gzip"
+	"io/ioutil"
 	"net/http"
 	"net/http"
 	"path/filepath"
 	"path/filepath"
 	"strings"
 	"strings"
+	"sync"
 
 
 	"gopkg.in/gin-gonic/gin.v1"
 	"gopkg.in/gin-gonic/gin.v1"
 )
 )
@@ -17,14 +19,22 @@ const (
 )
 )
 
 
 func Gzip(level int) gin.HandlerFunc {
 func Gzip(level int) gin.HandlerFunc {
+	var gzPool sync.Pool
+	gzPool.New = func() interface{} {
+		gz, err := gzip.NewWriterLevel(ioutil.Discard, level)
+		if err != nil {
+			panic(err)
+		}
+		return gz
+	}
 	return func(c *gin.Context) {
 	return func(c *gin.Context) {
 		if !shouldCompress(c.Request) {
 		if !shouldCompress(c.Request) {
 			return
 			return
 		}
 		}
-		gz, err := gzip.NewWriterLevel(c.Writer, level)
-		if err != nil {
-			return
-		}
+
+		gz := gzPool.Get().(*gzip.Writer)
+		defer gzPool.Put(gz)
+		gz.Reset(c.Writer)
 
 
 		c.Header("Content-Encoding", "gzip")
 		c.Header("Content-Encoding", "gzip")
 		c.Header("Vary", "Accept-Encoding")
 		c.Header("Vary", "Accept-Encoding")