From 4950ce485f7d931890fcfd2ee287b6df1b5db435 Mon Sep 17 00:00:00 2001
From: Dominik Braun <dominikbraun1997@web.de>
Date: Thu, 8 Aug 2019 07:59:02 +0200
Subject: Part 1: Optimize using compiler's inliner (#2687)

* optimized functions for inlining

* added note regarding ResponseWriterWrapper

* optimzed browseWrite* methods for FileServer

* created benchmarks for comparison

* creating browseListing instance in each function

* created benchmarks for openResponseWriter

* removed benchmarks of old implementations

* implemented sync.Pool for byte buffers

* using global sync.Pool for writing JSON/HTML
---
 modules/caddyhttp/fileserver/browse.go      |  6 ++--
 modules/caddyhttp/fileserver/browse_test.go | 54 +++++++++++++++++++++++++++++
 modules/caddyhttp/fileserver/staticfiles.go |  9 +++++
 3 files changed, 67 insertions(+), 2 deletions(-)
 create mode 100644 modules/caddyhttp/fileserver/browse_test.go

(limited to 'modules/caddyhttp/fileserver')

diff --git a/modules/caddyhttp/fileserver/browse.go b/modules/caddyhttp/fileserver/browse.go
index e0e6de2..91ebcd5 100644
--- a/modules/caddyhttp/fileserver/browse.go
+++ b/modules/caddyhttp/fileserver/browse.go
@@ -133,14 +133,16 @@ func (fsrv *FileServer) browseApplyQueryParams(w http.ResponseWriter, r *http.Re
 }
 
 func (fsrv *FileServer) browseWriteJSON(listing browseListing) (*bytes.Buffer, error) {
-	buf := new(bytes.Buffer)
+	buf := bufPool.Get().(*bytes.Buffer)
 	err := json.NewEncoder(buf).Encode(listing.Items)
+	bufPool.Put(buf)
 	return buf, err
 }
 
 func (fsrv *FileServer) browseWriteHTML(listing browseListing) (*bytes.Buffer, error) {
-	buf := new(bytes.Buffer)
+	buf := bufPool.Get().(*bytes.Buffer)
 	err := fsrv.Browse.template.Execute(buf, listing)
+	bufPool.Put(buf)
 	return buf, err
 }
 
diff --git a/modules/caddyhttp/fileserver/browse_test.go b/modules/caddyhttp/fileserver/browse_test.go
new file mode 100644
index 0000000..b1f7092
--- /dev/null
+++ b/modules/caddyhttp/fileserver/browse_test.go
@@ -0,0 +1,54 @@
+package fileserver
+
+import (
+	"html/template"
+	"testing"
+
+	"github.com/caddyserver/caddy/v2"
+)
+
+func BenchmarkBrowseWriteJSON(b *testing.B) {
+	fsrv := new(FileServer)
+	fsrv.Provision(caddy.Context{})
+	listing := browseListing{
+		Name:           "test",
+		Path:           "test",
+		CanGoUp:        false,
+		Items:          make([]fileInfo, 100),
+		NumDirs:        42,
+		NumFiles:       420,
+		Sort:           "",
+		Order:          "",
+		ItemsLimitedTo: 42,
+	}
+	b.ResetTimer()
+
+	for n := 0; n < b.N; n++ {
+		fsrv.browseWriteJSON(listing)
+	}
+}
+
+func BenchmarkBrowseWriteHTML(b *testing.B) {
+	fsrv := new(FileServer)
+	fsrv.Provision(caddy.Context{})
+	fsrv.Browse = &Browse{
+		TemplateFile: "",
+		template:     template.New("test"),
+	}
+	listing := browseListing{
+		Name:           "test",
+		Path:           "test",
+		CanGoUp:        false,
+		Items:          make([]fileInfo, 100),
+		NumDirs:        42,
+		NumFiles:       420,
+		Sort:           "",
+		Order:          "",
+		ItemsLimitedTo: 42,
+	}
+	b.ResetTimer()
+
+	for n := 0; n < b.N; n++ {
+		fsrv.browseWriteHTML(listing)
+	}
+}
diff --git a/modules/caddyhttp/fileserver/staticfiles.go b/modules/caddyhttp/fileserver/staticfiles.go
index 761dfc3..a66b753 100644
--- a/modules/caddyhttp/fileserver/staticfiles.go
+++ b/modules/caddyhttp/fileserver/staticfiles.go
@@ -15,6 +15,7 @@
 package fileserver
 
 import (
+	"bytes"
 	"fmt"
 	"html/template"
 	weakrand "math/rand"
@@ -25,6 +26,7 @@ import (
 	"path/filepath"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 
 	"github.com/caddyserver/caddy/v2"
@@ -46,6 +48,7 @@ type FileServer struct {
 	Hide       []string `json:"hide,omitempty"`
 	IndexNames []string `json:"index_names,omitempty"`
 	Browse     *Browse  `json:"browse,omitempty"`
+
 	// TODO: Content negotiation
 }
 
@@ -301,6 +304,12 @@ func calculateEtag(d os.FileInfo) string {
 
 var defaultIndexNames = []string{"index.html"}
 
+var bufPool = sync.Pool{
+	New: func() interface{} {
+		return new(bytes.Buffer)
+	},
+}
+
 const minBackoff, maxBackoff = 2, 5
 
 // Interface guards
-- 
cgit v1.2.3