v3: Improve Performance of c.Body() by 125% (#3090)

* Improve performance of Body()

* Add unit-test and benchmark for BodyRaw() with Immutable
pull/3092/head
Juan Calderon-Perez 2024-07-25 02:58:40 -04:00 committed by GitHub
parent fadedcb5be
commit 0592e01382
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 63 additions and 5 deletions

14
ctx.go
View File

@ -339,12 +339,16 @@ func (c *DefaultCtx) Body() []byte {
encodingOrder = []string{"", "", ""}
)
// faster than peek
c.Request().Header.VisitAll(func(key, value []byte) {
if c.app.getString(key) == HeaderContentEncoding {
headerEncoding = c.app.getString(value)
// Get Content-Encoding header
headerEncoding = utils.UnsafeString(c.Request().Header.ContentEncoding())
// If no encoding is provided, return the original body
if len(headerEncoding) == 0 {
if c.app.config.Immutable {
return utils.CopyBytes(c.fasthttp.Request.Body())
}
})
return c.fasthttp.Request.Body()
}
// Split and get the encodings list, in order to attend the
// rule defined at: https://www.rfc-editor.org/rfc/rfc9110#section-8.4-5

View File

@ -356,6 +356,26 @@ func Test_Ctx_Body(t *testing.T) {
require.Equal(t, []byte("john=doe"), c.Body())
}
// go test -run Test_Ctx_BodyRaw
func Test_Ctx_BodyRaw(t *testing.T) {
t.Parallel()
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
c.Request().SetBodyRaw([]byte("john=doe"))
require.Equal(t, []byte("john=doe"), c.BodyRaw())
}
// go test -run Test_Ctx_BodyRaw_Immutable
func Test_Ctx_BodyRaw_Immutable(t *testing.T) {
t.Parallel()
app := New(Config{Immutable: true})
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
c.Request().SetBodyRaw([]byte("john=doe"))
require.Equal(t, []byte("john=doe"), c.BodyRaw())
}
// go test -v -run=^$ -bench=Benchmark_Ctx_Body -benchmem -count=4
func Benchmark_Ctx_Body(b *testing.B) {
const input = "john=doe"
@ -373,6 +393,40 @@ func Benchmark_Ctx_Body(b *testing.B) {
require.Equal(b, []byte(input), c.Body())
}
// go test -v -run=^$ -bench=Benchmark_Ctx_BodyRaw -benchmem -count=4
func Benchmark_Ctx_BodyRaw(b *testing.B) {
const input = "john=doe"
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
c.Request().SetBodyRaw([]byte(input))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = c.BodyRaw()
}
require.Equal(b, []byte(input), c.BodyRaw())
}
// go test -v -run=^$ -bench=Benchmark_Ctx_BodyRaw_Immutable -benchmem -count=4
func Benchmark_Ctx_BodyRaw_Immutable(b *testing.B) {
const input = "john=doe"
app := New(Config{Immutable: true})
c := app.AcquireCtx(&fasthttp.RequestCtx{}).(*DefaultCtx) //nolint:errcheck, forcetypeassert // not needed
c.Request().SetBodyRaw([]byte(input))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = c.BodyRaw()
}
require.Equal(b, []byte(input), c.BodyRaw())
}
// go test -run Test_Ctx_Body_Immutable
func Test_Ctx_Body_Immutable(t *testing.T) {
t.Parallel()