Skip to content

Commit 25a564a

Browse files
authored
Merge pull request #3 from shanson7/reduceAllocs
Reduce allocs by pooling gzip.Writer objects
2 parents ad70bdb + d663e3d commit 25a564a

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

gzip.go

+34-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"net"
2424
"net/http"
2525
"strings"
26+
"sync"
2627

2728
"github.com/klauspost/compress/gzip"
2829
"gopkg.in/macaron.v1"
@@ -42,6 +43,32 @@ type nopCloser struct {
4243

4344
func (nopCloser) Close() error { return nil }
4445

46+
type WriterPool struct {
47+
pool sync.Pool
48+
}
49+
50+
func NewWriterPool() *WriterPool {
51+
return &WriterPool{pool: sync.Pool{
52+
New: func() interface{} { return nil },
53+
}}
54+
}
55+
56+
func (wp *WriterPool) Get(rw macaron.ResponseWriter) *gzip.Writer {
57+
ret := wp.pool.Get()
58+
if ret == nil {
59+
ret = gzip.NewWriter(rw)
60+
} else {
61+
ret.(*gzip.Writer).Reset(rw)
62+
}
63+
return ret.(*gzip.Writer)
64+
}
65+
66+
func (wp *WriterPool) Put(w *gzip.Writer) {
67+
wp.pool.Put(w)
68+
}
69+
70+
var writerPool WriterPool
71+
4572
/*
4673
Gzip middleware inspired by https://github.com/go-macaron/gzip
4774
@@ -97,7 +124,7 @@ func (grw *gzipResponseWriter) setup() {
97124
headers := grw.Header()
98125
headers.Set(_HEADER_CONTENT_ENCODING, "gzip")
99126
headers.Set(_HEADER_VARY, _HEADER_ACCEPT_ENCODING)
100-
grw.w = gzip.NewWriter(grw.ResponseWriter)
127+
grw.w = writerPool.Get(grw.ResponseWriter)
101128
}
102129
}
103130

@@ -107,6 +134,12 @@ func (grw *gzipResponseWriter) close() {
107134
return
108135
}
109136
grw.w.Close()
137+
138+
if poolWriter, ok := grw.w.(*gzip.Writer); ok {
139+
writerPool.Put(poolWriter)
140+
}
141+
142+
grw.w = nil
110143
}
111144

112145
func (grw *gzipResponseWriter) Write(p []byte) (int, error) {

gzip_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,24 @@ func Test_GzipPanic(t *testing.T) {
162162
So(before, ShouldBeTrue)
163163
})
164164
}
165+
166+
func BenchmarkGzip(b *testing.B) {
167+
b.ReportAllocs()
168+
b.ResetTimer()
169+
170+
m := macaron.New()
171+
m.Use(Gziper())
172+
m.Get("/", func() string { return "hello world!" })
173+
174+
for n := 0; n < b.N; n++ {
175+
resp := httptest.NewRecorder()
176+
req, err := http.NewRequest("GET", "/", nil)
177+
if err != nil {
178+
b.Error("Unexpected error = ", err)
179+
}
180+
181+
resp = httptest.NewRecorder()
182+
req.Header.Set(_HEADER_ACCEPT_ENCODING, "gzip")
183+
m.ServeHTTP(resp, req)
184+
}
185+
}

0 commit comments

Comments
 (0)