Repository: caddyserver/caddy (language: go)

Issue:
Use `sync.Pool` to reduce `lengthReader` allocations
In https://github.com/caddyserver/caddy/pull/5461 we introduced `lengthReader` to count the amount of bytes read from the request body.

We're allocating a new `lengthReader` on each request though (but only requests with a body, so not GETs). This is inefficient, it could be improved by using `sync.Pool` to reuse allocated `lengthReader` structs.


Discussion / hints:
Hi @francislavoie, I would like to work on this issue. Are there any benchmarks that I can use to verify the performance impact of the change? Thanks!
You can write a [simple benchmark test](https://pkg.go.dev/testing) to measure allocations and such. :+1:
Hi, is this issue being worked upon? I can take it up otherwise.
PRs are always welcome :+1: 
@perhapsmaple could you please let me know if you are still working on this? If not, can I please take this up!   

Fix patch:
diff --git a/modules/caddyhttp/server.go b/modules/caddyhttp/server.go
index cf176094716..54e8d2dc828 100644
--- a/modules/caddyhttp/server.go
+++ b/modules/caddyhttp/server.go
@@ -319,7 +319,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		// so we can track the number of bytes read from it
 		var bodyReader *lengthReader
 		if r.Body != nil {
-			bodyReader = &lengthReader{Source: r.Body}
+			bodyReader = getLengthReader(r.Body)
+			defer putLengthReader(bodyReader)
 			r.Body = bodyReader
 		}
 
@@ -911,6 +912,24 @@ type lengthReader struct {
 	Length int
 }
 
+var lengthReaderPool = sync.Pool{
+	New: func() interface{} {
+		return &lengthReader{}
+	},
+}
+
+func getLengthReader(source io.ReadCloser) *lengthReader {
+	reader := lengthReaderPool.Get().(*lengthReader)
+	reader.Source = source
+	return reader
+}
+
+func putLengthReader(reader *lengthReader) {
+	reader.Source = nil
+	reader.Length = 0
+	lengthReaderPool.Put(reader)
+}
+
 func (r *lengthReader) Read(b []byte) (int, error) {
 	n, err := r.Source.Read(b)
 	r.Length += n


Test patch: