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