summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--caddy.go12
-rw-r--r--modules/caddyhttp/encode/encode.go21
-rw-r--r--modules/caddyhttp/encode/encode_test.go12
-rw-r--r--modules/caddyhttp/fileserver/browse.go6
-rw-r--r--modules/caddyhttp/fileserver/browse_test.go54
-rw-r--r--modules/caddyhttp/fileserver/staticfiles.go9
6 files changed, 104 insertions, 10 deletions
diff --git a/caddy.go b/caddy.go
index 5a5349e..c30eccf 100644
--- a/caddy.go
+++ b/caddy.go
@@ -208,8 +208,16 @@ func (d *Duration) UnmarshalJSON(b []byte) error {
// If no version information is available, a non-nil
// value will still be returned, but with an
// unknown version.
-func GoModule() debug.Module {
- mod := debug.Module{Version: "unknown"}
+func GoModule() *debug.Module {
+ var mod debug.Module
+ return goModule(&mod)
+}
+
+// goModule holds the actual implementation of GoModule.
+// Allocating debug.Module in GoModule() and passing a
+// reference to goModule enables mid-stack inlining.
+func goModule(mod *debug.Module) *debug.Module {
+ mod.Version = "unknown"
bi, ok := debug.ReadBuildInfo()
if ok {
mod.Path = bi.Main.Path
diff --git a/modules/caddyhttp/encode/encode.go b/modules/caddyhttp/encode/encode.go
index c78ccb9..b2c1327 100644
--- a/modules/caddyhttp/encode/encode.go
+++ b/modules/caddyhttp/encode/encode.go
@@ -93,14 +93,23 @@ func (enc *Encode) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyh
// encode the response with encodingName. The returned response writer MUST
// be closed after the handler completes.
func (enc *Encode) openResponseWriter(encodingName string, w http.ResponseWriter) *responseWriter {
+ var rw responseWriter
+ return enc.initResponseWriter(&rw, encodingName, w)
+}
+
+// initResponseWriter initializes the responseWriter instance
+// allocated in openResponseWriter, enabling mid-stack inlining.
+func (enc *Encode) initResponseWriter(rw *responseWriter, encodingName string, wrappedRW http.ResponseWriter) *responseWriter {
buf := bufPool.Get().(*bytes.Buffer)
buf.Reset()
- return &responseWriter{
- ResponseWriterWrapper: &caddyhttp.ResponseWriterWrapper{ResponseWriter: w},
- encodingName: encodingName,
- buf: buf,
- config: enc,
- }
+
+ // The allocation of ResponseWriterWrapper might be optimized as well.
+ rw.ResponseWriterWrapper = &caddyhttp.ResponseWriterWrapper{ResponseWriter: wrappedRW}
+ rw.encodingName = encodingName
+ rw.buf = buf
+ rw.config = enc
+
+ return rw
}
// responseWriter writes to an underlying response writer
diff --git a/modules/caddyhttp/encode/encode_test.go b/modules/caddyhttp/encode/encode_test.go
new file mode 100644
index 0000000..79eae3c
--- /dev/null
+++ b/modules/caddyhttp/encode/encode_test.go
@@ -0,0 +1,12 @@
+package encode
+
+import (
+ "testing"
+)
+
+func BenchmarkOpenResponseWriter(b *testing.B) {
+ enc := new(Encode)
+ for n := 0; n < b.N; n++ {
+ enc.openResponseWriter("test", nil)
+ }
+}
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