From c8c51ee78331e2f19ca936ddd1fdbe0ad86fd8a3 Mon Sep 17 00:00:00 2001 From: RW Date: Fri, 5 Apr 2024 08:29:39 +0200 Subject: [PATCH] performance optimizations (#2947) * performance optimizations * add a new benchmark that tests the simple flow this will be used to make differences between version 2 and 3 directly visible * remove redundant ctx.Reset call * Add a new benchmark that tests the ctx acquire and release flow this will be used to show differences between version 2 and 3 directly * Add a new benchmark that tests the ctx acquire and release flow this will be used to show differences between version 2 and 3 directly --- app_test.go | 62 ++++++++++++++++++++++++++++++++++++++++-------- ctx_interface.go | 53 +++++++---------------------------------- router.go | 1 - 3 files changed, 61 insertions(+), 55 deletions(-) diff --git a/app_test.go b/app_test.go index f0e42a0848..39890ead48 100644 --- a/app_test.go +++ b/app_test.go @@ -1408,16 +1408,6 @@ func Test_App_Next_Method(t *testing.T) { require.Equal(t, 404, resp.StatusCode, "Status code") } -// go test -v -run=^$ -bench=Benchmark_AcquireCtx -benchmem -count=4 -func Benchmark_AcquireCtx(b *testing.B) { - app := New() - for n := 0; n < b.N; n++ { - c := app.AcquireCtx(&fasthttp.RequestCtx{}) - - app.ReleaseCtx(c) - } -} - // go test -v -run=^$ -bench=Benchmark_NewError -benchmem -count=4 func Benchmark_NewError(b *testing.B) { for n := 0; n < b.N; n++ { @@ -1975,3 +1965,55 @@ func Test_Route_Naming_Issue_2671_2685(t *testing.T) { sRoute2 := app.GetRoute("simple-route2") require.Equal(t, "/simple-route", sRoute2.Path) } + +// go test -v -run=^$ -bench=Benchmark_Communication_Flow -benchmem -count=4 +func Benchmark_Communication_Flow(b *testing.B) { + app := New() + + app.Get("/", func(c Ctx) error { + return c.SendString("Hello, World!") + }) + + h := app.Handler() + + fctx := &fasthttp.RequestCtx{} + fctx.Request.Header.SetMethod(MethodGet) + fctx.Request.SetRequestURI("/") + + b.ReportAllocs() + b.ResetTimer() + + for n := 0; n < b.N; n++ { + h(fctx) + } + + require.Equal(b, 200, fctx.Response.Header.StatusCode()) + require.Equal(b, "Hello, World!", string(fctx.Response.Body())) +} + +// go test -v -run=^$ -bench=Benchmark_Ctx_AcquireReleaseFlow -benchmem -count=4 +func Benchmark_Ctx_AcquireReleaseFlow(b *testing.B) { + app := New() + + fctx := &fasthttp.RequestCtx{} + + b.Run("withoutRequestCtx", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + + for n := 0; n < b.N; n++ { + c, _ := app.AcquireCtx(fctx).(*DefaultCtx) //nolint:errcheck // not needed + app.ReleaseCtx(c) + } + }) + + b.Run("withRequestCtx", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + + for n := 0; n < b.N; n++ { + c, _ := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck // not needed + app.ReleaseCtx(c) + } + }) +} diff --git a/ctx_interface.go b/ctx_interface.go index cb867ff2c0..bb8cdec260 100644 --- a/ctx_interface.go +++ b/ctx_interface.go @@ -375,9 +375,6 @@ type Ctx interface { // ClientHelloInfo return CHI from context ClientHelloInfo() *tls.ClientHelloInfo - // SetReq resets fields of context that is relating to request. - setReq(fctx *fasthttp.RequestCtx) - // Release is a method to reset context fields when to use ReleaseCtx() release() } @@ -407,16 +404,6 @@ func NewDefaultCtx(app *App) *DefaultCtx { return &DefaultCtx{ // Set app reference app: app, - - // Reset route and handler index - indexRoute: -1, - indexHandler: 0, - - // Reset matched flag - matched: false, - - // reset base uri - baseURI: "", } } @@ -452,32 +439,26 @@ func (app *App) ReleaseCtx(c Ctx) { // Reset is a method to reset context fields by given request when to use server handlers. func (c *DefaultCtx) Reset(fctx *fasthttp.RequestCtx) { + // Reset route and handler index + c.indexRoute = -1 + c.indexHandler = 0 + // Reset matched flag + c.matched = false // Set paths c.pathOriginal = c.app.getString(fctx.URI().PathOriginal()) - - // Attach *fasthttp.RequestCtx to ctx - c.setReq(fctx) - // Set method c.method = c.app.getString(fctx.Request.Header.Method()) c.methodINT = c.app.methodInt(c.method) - + // Attach *fasthttp.RequestCtx to ctx + c.fasthttp = fctx + // reset base uri + c.baseURI = "" // Prettify path c.configDependentPaths() } // Release is a method to reset context fields when to use ReleaseCtx() func (c *DefaultCtx) release() { - // Reset route and handler index - c.indexRoute = -1 - c.indexHandler = 0 - - // Reset matched flag - c.matched = false - - // reset base uri - c.baseURI = "" - c.route = nil c.fasthttp = nil c.bind = nil @@ -489,22 +470,6 @@ func (c *DefaultCtx) release() { } } -// SetReq resets fields of context that is relating to request. -func (c *DefaultCtx) setReq(fctx *fasthttp.RequestCtx) { - // Set paths - c.pathOriginal = c.app.getString(fctx.URI().PathOriginal()) - - // Attach *fasthttp.RequestCtx to ctx - c.fasthttp = fctx - - // Set method - c.method = c.app.getString(fctx.Request.Header.Method()) - c.methodINT = c.app.methodInt(c.method) - - // Prettify path - c.configDependentPaths() -} - // Methods to use with next stack. func (c *DefaultCtx) getMethodINT() int { return c.methodINT diff --git a/router.go b/router.go index 4347c7ba9f..f65b4ece90 100644 --- a/router.go +++ b/router.go @@ -218,7 +218,6 @@ func (app *App) requestHandler(rctx *fasthttp.RequestCtx) { panic(errors.New("requestHandler: failed to type-assert to *DefaultCtx")) } } - c.Reset(rctx) defer app.ReleaseCtx(c) // handle invalid http method directly