produce less garbage; reuse buffers

This commit is contained in:
lemmi 2020-01-24 06:44:44 +01:00
parent 6ed3634876
commit b326aa66f5
1 changed files with 16 additions and 24 deletions

40
main.go
View File

@ -316,32 +316,21 @@ func render(w io.Writer, rs []route) error {
return t.Execute(w, data)
}
func renderBytes(rs *routeStats) ([]byte, error) {
var buf bytes.Buffer
err := render(&buf, rs.getLongest())
return buf.Bytes(), err
}
func compress(content []byte, err error) ([]byte, error) {
func compress(cw io.Writer, cr io.Reader, err error) error {
if err != nil {
return nil, err
return err
}
var compressbuf bytes.Buffer
cw, err := gzip.NewWriterLevel(&compressbuf, gzip.BestCompression)
gzw, err := gzip.NewWriterLevel(cw, gzip.BestCompression)
if err != nil {
return nil, err
return err
}
if _, err = cw.Write(content); err != nil {
return nil, err
if _, err = io.Copy(gzw, cr); err != nil {
return err
}
if err = cw.Close(); err != nil {
return nil, err
}
return compressbuf.Bytes(), nil
return gzw.Close()
}
func acceptGzip(h http.Header) bool {
@ -356,8 +345,8 @@ func acceptGzip(h http.Header) bool {
func cachedRender(rs *routeStats) http.HandlerFunc {
var m sync.Mutex
var timestamp time.Time
var content []byte
var compressed []byte
var content bytes.Buffer
var compressed bytes.Buffer
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Not Allowed", http.StatusMethodNotAllowed)
@ -377,8 +366,11 @@ func cachedRender(rs *routeStats) http.HandlerFunc {
var err error
m.Lock()
if time.Since(timestamp) > 5*time.Second {
content, err = renderBytes(rs)
compressed, err = compress(content, err)
content.Reset()
compressed.Reset()
err = render(&content, rs.getLongest())
err = compress(&compressed, bytes.NewReader(content.Bytes()), err)
timestamp = time.Now()
}
@ -399,8 +391,8 @@ func cachedRender(rs *routeStats) http.HandlerFunc {
w.Header().Add("Content-Encoding", "gzip")
}
w.Header().Set("Content-Length", strconv.FormatInt(int64(len(c)), 10))
http.ServeContent(w, r, "/", timestamp, bytes.NewReader(c))
w.Header().Set("Content-Length", strconv.FormatInt(int64(c.Len()), 10))
http.ServeContent(w, r, "/", timestamp, bytes.NewReader(c.Bytes()))
}
}