Skip to content

Commit

Permalink
šŸ› fix(middleware/adaptor): Reduce memory usage by replacing io.ReadAlā€¦
Browse files Browse the repository at this point in the history
ā€¦l() with io.Copy() (#2637)

* Replace io.ReadAll with io.Copy for Adaptor Middleware

* Add nolint to Close() during benchmark
  • Loading branch information
gaby authored Sep 19, 2023
1 parent 52f1eb9 commit 5d6552e
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 7 deletions.
9 changes: 2 additions & 7 deletions middleware/adaptor/adaptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,9 @@ func handlerFunc(app *fiber.App, h ...fiber.Handler) http.HandlerFunc {
defer fasthttp.ReleaseRequest(req)
// Convert net/http -> fasthttp request
if r.Body != nil {
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, utils.StatusMessage(fiber.StatusInternalServerError), fiber.StatusInternalServerError)
return
}
n, err := io.Copy(req.BodyWriter(), r.Body)
req.Header.SetContentLength(int(n))

req.Header.SetContentLength(len(body))
_, err = req.BodyWriter().Write(body)
if err != nil {
http.Error(w, utils.StatusMessage(fiber.StatusInternalServerError), fiber.StatusInternalServerError)
return
Expand Down
86 changes: 86 additions & 0 deletions middleware/adaptor/adaptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package adaptor

import (
"bytes"
"context"
"fmt"
"io"
Expand Down Expand Up @@ -485,3 +486,88 @@ func Test_ConvertRequest(t *testing.T) {
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, "Request URL: /test?hello=world&another=test", string(body))
}

// Benchmark for FiberHandlerFunc
func Benchmark_FiberHandlerFunc_1MB(b *testing.B) {
fiberH := func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
}
handlerFunc := FiberHandlerFunc(fiberH)

// Create body content
bodyContent := make([]byte, 1*1024*1024)
bodyBuffer := bytes.NewBuffer(bodyContent)

r := http.Request{
Method: http.MethodPost,
Body: http.NoBody,
}

// Replace the empty Body with our buffer
r.Body = io.NopCloser(bodyBuffer)
defer r.Body.Close() //nolint:errcheck // not needed

// Create recorder
w := httptest.NewRecorder()

b.ResetTimer()
for i := 0; i < b.N; i++ {
handlerFunc.ServeHTTP(w, &r)
}
}

func Benchmark_FiberHandlerFunc_10MB(b *testing.B) {
fiberH := func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
}
handlerFunc := FiberHandlerFunc(fiberH)

// Create body content
bodyContent := make([]byte, 10*1024*1024)
bodyBuffer := bytes.NewBuffer(bodyContent)

r := http.Request{
Method: http.MethodPost,
Body: http.NoBody,
}

// Replace the empty Body with our buffer
r.Body = io.NopCloser(bodyBuffer)
defer r.Body.Close() //nolint:errcheck // not needed

// Create recorder
w := httptest.NewRecorder()

b.ResetTimer()
for i := 0; i < b.N; i++ {
handlerFunc.ServeHTTP(w, &r)
}
}

func Benchmark_FiberHandlerFunc_50MB(b *testing.B) {
fiberH := func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
}
handlerFunc := FiberHandlerFunc(fiberH)

// Create body content
bodyContent := make([]byte, 50*1024*1024)
bodyBuffer := bytes.NewBuffer(bodyContent)

r := http.Request{
Method: http.MethodPost,
Body: http.NoBody,
}

// Replace the empty Body with our buffer
r.Body = io.NopCloser(bodyBuffer)
defer r.Body.Close() //nolint:errcheck // not needed

// Create recorder
w := httptest.NewRecorder()

b.ResetTimer()
for i := 0; i < b.N; i++ {
handlerFunc.ServeHTTP(w, &r)
}
}

0 comments on commit 5d6552e

Please sign in to comment.