gofiber / fiber

⚡️ Express inspired web framework written in Go
https://gofiber.io
MIT License
33.16k stars 1.63k forks source link

🚀 v3 Request: New Parser for Binding #2002

Open efectn opened 2 years ago

efectn commented 2 years ago

Feature Description

Currently, Fiber binding uses gorilla/schema and it's very slow and doesn't support multipart files (https://github.com/gofiber/fiber/issues/1967).

We should write more performant, powerful parser acording to the needs of Fiber.

Check: https://github.com/gofiber/fiber/pull/1981#issuecomment-1207505201

Additional Context (optional)

No response

Code Snippet (optional)

package main

import "github.com/gofiber/fiber/v2"
import "log"

func main() {
  app := fiber.New()

  // An example to describe the feature

  log.Fatal(app.Listen(":3000"))
}

Checklist:

trim21 commented 2 years ago

I'd like to add another context about this impl.

Key point here is not to use methods of fiber.Ctx, but to build a decoder for a Request struct and reuse it in the future.

with a function decorator, the decoder are pre-compiled and cached by nature. and this cached don't have overhead like map access.

If the decoder is not pre-compiled, it's not that fast and low alloc:

func Benchmark_lib_unmarshal(b *testing.B) {
    decode := inj.CompileParser(Req{})
    ctx := getCtx()
    for i := 0; i < b.N; i++ {
        _, err := decode(ctx)
        if err != nil {
            b.Error(err)
            b.FailNow()
        }
    }
}

func Benchmark_lib_unmarshal_with_compile(b *testing.B) {
-   decode := inj.CompileParser(Req{})
    ctx := getCtx()
    for i := 0; i < b.N; i++ {
+       decode := inj.CompileParser(Req{})
        _, err := decode(ctx)
        if err != nil {
            b.Error(err)
            b.FailNow()
        }
    }
}
cpu: AMD Ryzen 7 5800X 8-Core Processor
Benchmark_unmarshal_by_hand-16                          14774758                68.03 ns/op            0 B/op          0 allocs/op
Benchmark_lib_unmarshal-16                               6359373               196.7 ns/op            96 B/op          2 allocs/op
Benchmark_lib_unmarshal_with_compile-16                  1222078               992.6 ns/op           672 B/op         22 allocs/op
BenchmarkGorillaSchema_map_to_struct_only-16              419390              2898 ns/op             904 B/op         49 allocs/op
ReneWerner87 commented 2 years ago

if you have ideas or performance improvements, feel free to create a pull request with them and we'll see together how to get the best out of the respective functionalities.

any comments or improvements are always welcome

once the whole thing is released, it's hard to bend it, because non downward compatible changes require a new major version

trim21 commented 2 years ago

I'll send a PR later

wangjq4214 commented 2 years ago

I want to know if the minimum go version that will be supported in the next release will be 1.18?

trim21 commented 2 years ago

I guess yes https://github.com/gofiber/fiber/blob/v3-beta/go.mod#L3 , and my pr need new generic support .

efectn commented 2 years ago

I want to know if the minimum go version that will be supported in the next release will be 1.18?

Yes. v3 will support last 2 major versions of Go