mirror of https://github.com/gofiber/fiber.git
v3: Improve performance of Adaptor Middleware (#3078)
* Improve performance of adaptor middleware by over 50% * Update whats_new documentation * Remove fasthttp.Request pool * Update whats_new.mdpull/3075/head
parent
58d07f091d
commit
091a59472c
|
@ -254,6 +254,34 @@ DRAFT section
|
|||
|
||||
## 🧬 Middlewares
|
||||
|
||||
### Adaptor
|
||||
|
||||
The adaptor middleware has been significantly optimized for performance and efficiency. Key improvements include reduced response times, lower memory usage, and fewer memory allocations. These changes make the middleware more reliable and capable of handling higher loads effectively. Enhancements include the introduction of a `sync.Pool` for managing `fasthttp.RequestCtx` instances and better HTTP request and response handling between net/http and fasthttp contexts.
|
||||
|
||||
| Payload Size | Metric | V2 | V3 | Percent Change |
|
||||
|--------------|------------------|-----------|----------|-------------------|
|
||||
| 100KB | Execution Time | 1056 ns/op| 588.6 ns/op | -44.25% |
|
||||
| | Memory Usage | 2644 B/op | 254 B/op | -90.39% |
|
||||
| | Allocations | 16 allocs/op | 5 allocs/op | -68.75% |
|
||||
| 500KB | Execution Time | 1061 ns/op| 562.9 ns/op | -46.94% |
|
||||
| | Memory Usage | 2644 B/op | 248 B/op | -90.62% |
|
||||
| | Allocations | 16 allocs/op | 5 allocs/op | -68.75% |
|
||||
| 1MB | Execution Time | 1080 ns/op| 629.7 ns/op | -41.68% |
|
||||
| | Memory Usage | 2646 B/op | 267 B/op | -89.91% |
|
||||
| | Allocations | 16 allocs/op | 5 allocs/op | -68.75% |
|
||||
| 5MB | Execution Time | 1093 ns/op| 540.3 ns/op | -50.58% |
|
||||
| | Memory Usage | 2654 B/op | 254 B/op | -90.43% |
|
||||
| | Allocations | 16 allocs/op | 5 allocs/op | -68.75% |
|
||||
| 10MB | Execution Time | 1044 ns/op| 533.1 ns/op | -48.94% |
|
||||
| | Memory Usage | 2665 B/op | 258 B/op | -90.32% |
|
||||
| | Allocations | 16 allocs/op | 5 allocs/op | -68.75% |
|
||||
| 25MB | Execution Time | 1069 ns/op| 540.7 ns/op | -49.42% |
|
||||
| | Memory Usage | 2706 B/op | 289 B/op | -89.32% |
|
||||
| | Allocations | 16 allocs/op | 5 allocs/op | -68.75% |
|
||||
| 50MB | Execution Time | 1137 ns/op| 554.6 ns/op | -51.21% |
|
||||
| | Memory Usage | 2734 B/op | 298 B/op | -89.10% |
|
||||
| | Allocations | 16 allocs/op | 5 allocs/op | -68.75% |
|
||||
|
||||
### Cache
|
||||
|
||||
We are excited to introduce a new option in our caching middleware: Cache Invalidator. This feature provides greater control over cache management, allowing you to define a custom conditions for invalidating cache entries.
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
|
@ -13,6 +14,12 @@ import (
|
|||
"github.com/valyala/fasthttp/fasthttpadaptor"
|
||||
)
|
||||
|
||||
var ctxPool = sync.Pool{
|
||||
New: func() any {
|
||||
return new(fasthttp.RequestCtx)
|
||||
},
|
||||
}
|
||||
|
||||
// HTTPHandlerFunc wraps net/http handler func to fiber handler
|
||||
func HTTPHandlerFunc(h http.HandlerFunc) fiber.Handler {
|
||||
return HTTPHandler(h)
|
||||
|
@ -82,12 +89,13 @@ func HTTPMiddleware(mw func(http.Handler) http.Handler) fiber.Handler {
|
|||
return func(c fiber.Ctx) error {
|
||||
var next bool
|
||||
nextHandler := http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
|
||||
next = true
|
||||
// Convert again in case request may modify by middleware
|
||||
next = true
|
||||
c.Request().Header.SetMethod(r.Method)
|
||||
c.Request().SetRequestURI(r.RequestURI)
|
||||
c.Request().SetHost(r.Host)
|
||||
c.Request().Header.SetHost(r.Host)
|
||||
|
||||
for key, val := range r.Header {
|
||||
for _, v := range val {
|
||||
c.Request().Header.Set(key, v)
|
||||
|
@ -124,9 +132,9 @@ func FiberApp(app *fiber.App) http.HandlerFunc {
|
|||
|
||||
func handlerFunc(app *fiber.App, h ...fiber.Handler) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// New fasthttp request
|
||||
req := fasthttp.AcquireRequest()
|
||||
defer fasthttp.ReleaseRequest(req)
|
||||
|
||||
// Convert net/http -> fasthttp request
|
||||
if r.Body != nil {
|
||||
n, err := io.Copy(req.BodyWriter(), r.Body)
|
||||
|
@ -141,26 +149,35 @@ func handlerFunc(app *fiber.App, h ...fiber.Handler) http.HandlerFunc {
|
|||
req.SetRequestURI(r.RequestURI)
|
||||
req.SetHost(r.Host)
|
||||
req.Header.SetHost(r.Host)
|
||||
|
||||
for key, val := range r.Header {
|
||||
for _, v := range val {
|
||||
req.Header.Set(key, v)
|
||||
}
|
||||
}
|
||||
|
||||
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil && err.(*net.AddrError).Err == "missing port in address" { //nolint:errorlint, forcetypeassert // overlinting
|
||||
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
|
||||
}
|
||||
|
||||
remoteAddr, err := net.ResolveTCPAddr("tcp", r.RemoteAddr)
|
||||
if err != nil {
|
||||
http.Error(w, utils.StatusMessage(fiber.StatusInternalServerError), fiber.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// New fasthttp Ctx
|
||||
var fctx fasthttp.RequestCtx
|
||||
// New fasthttp Ctx from pool
|
||||
fctx := ctxPool.Get().(*fasthttp.RequestCtx) //nolint:forcetypeassert,errcheck // overlinting
|
||||
fctx.Response.Reset()
|
||||
fctx.Request.Reset()
|
||||
defer ctxPool.Put(fctx)
|
||||
fctx.Init(req, remoteAddr, nil)
|
||||
|
||||
if len(h) > 0 {
|
||||
// New fiber Ctx
|
||||
ctx := app.AcquireCtx(&fctx)
|
||||
ctx := app.AcquireCtx(fctx)
|
||||
defer app.ReleaseCtx(ctx)
|
||||
|
||||
// Execute fiber Ctx
|
||||
err := h[0](ctx)
|
||||
if err != nil {
|
||||
|
@ -168,10 +185,10 @@ func handlerFunc(app *fiber.App, h ...fiber.Handler) http.HandlerFunc {
|
|||
}
|
||||
} else {
|
||||
// Execute fasthttp Ctx though app.Handler
|
||||
app.Handler()(&fctx)
|
||||
app.Handler()(fctx)
|
||||
}
|
||||
|
||||
// Convert fasthttp Ctx > net/http
|
||||
// Convert fasthttp Ctx -> net/http
|
||||
fctx.Response.Header.VisitAll(func(k, v []byte) {
|
||||
w.Header().Add(string(k), string(v))
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue