commit 75553eeeb0341ed3fd2f5b03061576f96b9ad5af Author: Eduard Urbach Date: Wed Mar 13 22:33:41 2024 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c71279c --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +* +!*/ +!.gitignore +!*.go +!*.md +!*.mod +!*.sum +!*.txt \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e55d8bd --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# benchmarks + +## Web + +``` +BenchmarkAkyoto/Hello-12 29872866 38.33 ns/op 0 B/op 0 allocs/op +BenchmarkAkyoto/GitHub-12 15900098 72.91 ns/op 0 B/op 0 allocs/op +BenchmarkChi/Hello-12 4328472 275.4 ns/op 336 B/op 2 allocs/op +BenchmarkChi/GitHub-12 3447220 331.1 ns/op 336 B/op 2 allocs/op +BenchmarkEcho/Hello-12 19503808 51.41 ns/op 0 B/op 0 allocs/op +BenchmarkEcho/GitHub-12 10899865 110.8 ns/op 0 B/op 0 allocs/op +BenchmarkGin/Hello-12 21826857 52.77 ns/op 0 B/op 0 allocs/op +BenchmarkGin/GitHub-12 11601283 101.9 ns/op 0 B/op 0 allocs/op +BenchmarkWay/Hello-12 5323245 222.9 ns/op 307 B/op 3 allocs/op +BenchmarkWay/GitHub-12 114187 9397 ns/op 4979 B/op 177 allocs/op +``` \ No newline at end of file diff --git a/web/akyoto_test.go b/web/akyoto_test.go new file mode 100644 index 0000000..0b7cf06 --- /dev/null +++ b/web/akyoto_test.go @@ -0,0 +1,21 @@ +package main_test + +import ( + "testing" + + "git.akyoto.dev/go/server" +) + +func BenchmarkAkyoto(b *testing.B) { + bench( + b, + func() *server.Server { + return server.New() + }, + func(s *server.Server, method string, path string) { + s.Router.Add(method, path, func(ctx server.Context) error { + return ctx.Bytes(payload) + }) + }, + ) +} diff --git a/web/chi_test.go b/web/chi_test.go new file mode 100644 index 0000000..04c26fa --- /dev/null +++ b/web/chi_test.go @@ -0,0 +1,22 @@ +package main_test + +import ( + "net/http" + "testing" + + "github.com/go-chi/chi/v5" +) + +func BenchmarkChi(b *testing.B) { + bench( + b, + func() *chi.Mux { + return chi.NewRouter() + }, + func(mux *chi.Mux, method string, path string) { + mux.MethodFunc(method, path, func(w http.ResponseWriter, r *http.Request) { + w.Write(payload) + }) + }, + ) +} diff --git a/web/common_test.go b/web/common_test.go new file mode 100644 index 0000000..bdc5deb --- /dev/null +++ b/web/common_test.go @@ -0,0 +1,52 @@ +package main_test + +import ( + "net/http" + "net/http/httptest" + "testing" + + "git.akyoto.dev/go/router/testdata" +) + +var ( + helloRoute = "/" + githubRoute = "/repos/:owner/:repo" + payloadString = "Hello" + payload = []byte(payloadString) +) + +// NullResponse implements the http.ResponseWriter interface with +// empty methods to better understand memory usage in benchmarks. +type NullResponse struct{} + +func (r *NullResponse) Header() http.Header { return http.Header{} } +func (r *NullResponse) Write([]byte) (int, error) { return 0, nil } +func (r *NullResponse) WriteHeader(int) {} + +// bench is the core benchmarking function. +func bench[T http.Handler](b *testing.B, init func() T, addRoute func(T, string, string)) { + b.Run("Hello", func(b *testing.B) { + request := httptest.NewRequest("GET", helloRoute, nil) + response := &NullResponse{} + router := init() + addRoute(router, "GET", "/") + + for range b.N { + router.ServeHTTP(response, request) + } + }) + + b.Run("GitHub", func(b *testing.B) { + request := httptest.NewRequest("GET", githubRoute, nil) + response := &NullResponse{} + router := init() + + for _, route := range testdata.Routes("testdata/github.txt") { + addRoute(router, route.Method, route.Path) + } + + for range b.N { + router.ServeHTTP(response, request) + } + }) +} diff --git a/web/echo_test.go b/web/echo_test.go new file mode 100644 index 0000000..541fb24 --- /dev/null +++ b/web/echo_test.go @@ -0,0 +1,22 @@ +package main_test + +import ( + "testing" + + "github.com/labstack/echo/v4" +) + +func BenchmarkEcho(b *testing.B) { + bench( + b, + func() *echo.Echo { + return echo.New() + }, + func(e *echo.Echo, method string, path string) { + e.Add(method, path, func(c echo.Context) error { + _, err := c.Response().Write(payload) + return err + }) + }, + ) +} diff --git a/web/gin_test.go b/web/gin_test.go new file mode 100644 index 0000000..5881bb5 --- /dev/null +++ b/web/gin_test.go @@ -0,0 +1,23 @@ +package main_test + +import ( + "testing" + + "github.com/gin-gonic/gin" +) + +func BenchmarkGin(b *testing.B) { + gin.SetMode(gin.ReleaseMode) + + bench( + b, + func() *gin.Engine { + return gin.New() + }, + func(g *gin.Engine, method string, path string) { + g.Handle(method, path, func(ctx *gin.Context) { + ctx.Writer.Write(payload) + }) + }, + ) +} diff --git a/web/go.mod b/web/go.mod new file mode 100644 index 0000000..31baef4 --- /dev/null +++ b/web/go.mod @@ -0,0 +1,44 @@ +module git.akyoto.dev/go/benchmarks/web + +go 1.22.1 + +require ( + git.akyoto.dev/go/router v0.1.3 + git.akyoto.dev/go/server v0.0.0-20240313191801-c13dbc55d263 + github.com/go-chi/chi/v5 v5.0.12 + github.com/labstack/echo/v4 v4.11.4 + github.com/matryer/way v0.0.0-20180416093233-9632d0c407b0 +) + +require ( + github.com/bytedance/sonic v1.9.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.9.1 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/labstack/gommon v0.4.2 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect + golang.org/x/arch v0.3.0 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/web/go.sum b/web/go.sum new file mode 100644 index 0000000..c78e570 --- /dev/null +++ b/web/go.sum @@ -0,0 +1,104 @@ +git.akyoto.dev/go/assert v0.1.3 h1:QwCUbmG4aZYsNk/OuRBz1zWVKmGlDUHhOnnDBfn8Qw8= +git.akyoto.dev/go/assert v0.1.3/go.mod h1:0GzMaM0eURuDwtGkJJkCsI7r2aUKr+5GmWNTFPgDocM= +git.akyoto.dev/go/router v0.1.3 h1:H4wJCYdDD3/i9miYSK/e5sCoGiXe9OX7KmgH4/Toa60= +git.akyoto.dev/go/router v0.1.3/go.mod h1:VfSsK/Z6fUhT3pWaAAnuAcj++bWRZD+bzNaqJoTAunU= +git.akyoto.dev/go/server v0.0.0-20240313191801-c13dbc55d263 h1:t5DctyOnTUPUMQsyHNZefIKYO4TjKq4wXt+2+e37PwY= +git.akyoto.dev/go/server v0.0.0-20240313191801-c13dbc55d263/go.mod h1:VVr9rDl+CPnQyXphXpOcpSovrjzPGsSk00PjUBHkx1c= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= +github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8= +github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8= +github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/matryer/way v0.0.0-20180416093233-9632d0c407b0 h1:KWiqy3hl8yCUPAq1frD0DKXKyn7d9h2nVhj2r5ISq2o= +github.com/matryer/way v0.0.0-20180416093233-9632d0c407b0/go.mod h1:stiJZfMq1xZPqvIyt2VsYMgLul8vf1nmL0D3KU70dEc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/web/testdata/github.txt b/web/testdata/github.txt new file mode 100644 index 0000000..fc85456 --- /dev/null +++ b/web/testdata/github.txt @@ -0,0 +1,203 @@ +GET /authorizations +GET /authorizations/:id +POST /authorizations +DELETE /authorizations/:id +GET /applications/:client_id/tokens/:access_token +DELETE /applications/:client_id/tokens +DELETE /applications/:client_id/tokens/:access_token +GET /events +GET /repos/:owner/:repo/events +GET /networks/:owner/:repo/events +GET /orgs/:org/events +GET /users/:user/received_events +GET /users/:user/received_events/public +GET /users/:user/events +GET /users/:user/events/public +GET /users/:user/events/orgs/:org +GET /feeds +GET /notifications +GET /repos/:owner/:repo/notifications +PUT /notifications +PUT /repos/:owner/:repo/notifications +GET /notifications/threads/:id +GET /notifications/threads/:id/subscription +PUT /notifications/threads/:id/subscription +DELETE /notifications/threads/:id/subscription +GET /repos/:owner/:repo/stargazers +GET /users/:user/starred +GET /user/starred +GET /user/starred/:owner/:repo +PUT /user/starred/:owner/:repo +DELETE /user/starred/:owner/:repo +GET /repos/:owner/:repo/subscribers +GET /users/:user/subscriptions +GET /user/subscriptions +GET /repos/:owner/:repo/subscription +PUT /repos/:owner/:repo/subscription +DELETE /repos/:owner/:repo/subscription +GET /user/subscriptions/:owner/:repo +PUT /user/subscriptions/:owner/:repo +DELETE /user/subscriptions/:owner/:repo +GET /users/:user/gists +GET /gists +GET /gists/:id +POST /gists +PUT /gists/:id/star +DELETE /gists/:id/star +GET /gists/:id/star +POST /gists/:id/forks +DELETE /gists/:id +GET /repos/:owner/:repo/git/blobs/:sha +POST /repos/:owner/:repo/git/blobs +GET /repos/:owner/:repo/git/commits/:sha +POST /repos/:owner/:repo/git/commits +GET /repos/:owner/:repo/git/refs +POST /repos/:owner/:repo/git/refs +GET /repos/:owner/:repo/git/tags/:sha +POST /repos/:owner/:repo/git/tags +GET /repos/:owner/:repo/git/trees/:sha +POST /repos/:owner/:repo/git/trees +GET /issues +GET /user/issues +GET /orgs/:org/issues +GET /repos/:owner/:repo/issues +GET /repos/:owner/:repo/issues/:number +POST /repos/:owner/:repo/issues +GET /repos/:owner/:repo/assignees +GET /repos/:owner/:repo/assignees/:assignee +GET /repos/:owner/:repo/issues/:number/comments +POST /repos/:owner/:repo/issues/:number/comments +GET /repos/:owner/:repo/issues/:number/events +GET /repos/:owner/:repo/labels +GET /repos/:owner/:repo/labels/:name +POST /repos/:owner/:repo/labels +DELETE /repos/:owner/:repo/labels/:name +GET /repos/:owner/:repo/issues/:number/labels +POST /repos/:owner/:repo/issues/:number/labels +DELETE /repos/:owner/:repo/issues/:number/labels/:name +PUT /repos/:owner/:repo/issues/:number/labels +DELETE /repos/:owner/:repo/issues/:number/labels +GET /repos/:owner/:repo/milestones/:number/labels +GET /repos/:owner/:repo/milestones +GET /repos/:owner/:repo/milestones/:number +POST /repos/:owner/:repo/milestones +DELETE /repos/:owner/:repo/milestones/:number +GET /emojis +GET /gitignore/templates +GET /gitignore/templates/:name +POST /markdown +POST /markdown/raw +GET /meta +GET /rate_limit +GET /users/:user/orgs +GET /user/orgs +GET /orgs/:org +GET /orgs/:org/members +GET /orgs/:org/members/:user +DELETE /orgs/:org/members/:user +GET /orgs/:org/public_members +GET /orgs/:org/public_members/:user +PUT /orgs/:org/public_members/:user +DELETE /orgs/:org/public_members/:user +GET /orgs/:org/teams +GET /teams/:id +POST /orgs/:org/teams +DELETE /teams/:id +GET /teams/:id/members +GET /teams/:id/members/:user +PUT /teams/:id/members/:user +DELETE /teams/:id/members/:user +GET /teams/:id/repos +GET /teams/:id/repos/:owner/:repo +PUT /teams/:id/repos/:owner/:repo +DELETE /teams/:id/repos/:owner/:repo +GET /user/teams +GET /repos/:owner/:repo/pulls +GET /repos/:owner/:repo/pulls/:number +POST /repos/:owner/:repo/pulls +GET /repos/:owner/:repo/pulls/:number/commits +GET /repos/:owner/:repo/pulls/:number/files +GET /repos/:owner/:repo/pulls/:number/merge +PUT /repos/:owner/:repo/pulls/:number/merge +GET /repos/:owner/:repo/pulls/:number/comments +PUT /repos/:owner/:repo/pulls/:number/comments +GET /user/repos +GET /users/:user/repos +GET /orgs/:org/repos +GET /repositories +POST /user/repos +POST /orgs/:org/repos +GET /repos/:owner/:repo +GET /repos/:owner/:repo/contributors +GET /repos/:owner/:repo/languages +GET /repos/:owner/:repo/teams +GET /repos/:owner/:repo/tags +GET /repos/:owner/:repo/branches +GET /repos/:owner/:repo/branches/:branch +DELETE /repos/:owner/:repo +GET /repos/:owner/:repo/collaborators +GET /repos/:owner/:repo/collaborators/:user +PUT /repos/:owner/:repo/collaborators/:user +DELETE /repos/:owner/:repo/collaborators/:user +GET /repos/:owner/:repo/comments +GET /repos/:owner/:repo/commits/:sha/comments +POST /repos/:owner/:repo/commits/:sha/comments +GET /repos/:owner/:repo/comments/:id +DELETE /repos/:owner/:repo/comments/:id +GET /repos/:owner/:repo/commits +GET /repos/:owner/:repo/commits/:sha +GET /repos/:owner/:repo/readme +GET /repos/:owner/:repo/keys +GET /repos/:owner/:repo/keys/:id +POST /repos/:owner/:repo/keys +DELETE /repos/:owner/:repo/keys/:id +GET /repos/:owner/:repo/downloads +GET /repos/:owner/:repo/downloads/:id +DELETE /repos/:owner/:repo/downloads/:id +GET /repos/:owner/:repo/forks +POST /repos/:owner/:repo/forks +GET /repos/:owner/:repo/hooks +GET /repos/:owner/:repo/hooks/:id +POST /repos/:owner/:repo/hooks +POST /repos/:owner/:repo/hooks/:id/tests +DELETE /repos/:owner/:repo/hooks/:id +POST /repos/:owner/:repo/merges +GET /repos/:owner/:repo/releases +GET /repos/:owner/:repo/releases/:id +POST /repos/:owner/:repo/releases +DELETE /repos/:owner/:repo/releases/:id +GET /repos/:owner/:repo/releases/:id/assets +GET /repos/:owner/:repo/stats/contributors +GET /repos/:owner/:repo/stats/commit_activity +GET /repos/:owner/:repo/stats/code_frequency +GET /repos/:owner/:repo/stats/participation +GET /repos/:owner/:repo/stats/punch_card +GET /repos/:owner/:repo/statuses/:ref +POST /repos/:owner/:repo/statuses/:ref +GET /search/repositories +GET /search/code +GET /search/issues +GET /search/users +GET /legacy/issues/search/:owner/:repository/:state/:keyword +GET /legacy/repos/search/:keyword +GET /legacy/user/search/:keyword +GET /legacy/user/email/:email +GET /users/:user +GET /user +GET /users +GET /user/emails +POST /user/emails +DELETE /user/emails +GET /users/:user/followers +GET /user/followers +GET /users/:user/following +GET /user/following +GET /user/following/:user +GET /users/:user/following/:target_user +PUT /user/following/:user +DELETE /user/following/:user +GET /users/:user/keys +GET /user/keys +GET /user/keys/:id +POST /user/keys +DELETE /user/keys/:id \ No newline at end of file diff --git a/web/way_test.go b/web/way_test.go new file mode 100644 index 0000000..4da742f --- /dev/null +++ b/web/way_test.go @@ -0,0 +1,42 @@ +package main_test + +import ( + "net/http" + "net/http/httptest" + "testing" + + "git.akyoto.dev/go/router/testdata" + "github.com/matryer/way" +) + +func BenchmarkWay(b *testing.B) { + response := &NullResponse{} + + b.Run("Hello", func(b *testing.B) { + request := httptest.NewRequest("GET", helloRoute, nil) + router := way.NewRouter() + + router.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) { + w.Write(payload) + }) + + for range b.N { + router.ServeHTTP(response, request) + } + }) + + b.Run("GitHub", func(b *testing.B) { + request := httptest.NewRequest("GET", githubRoute, nil) + router := way.NewRouter() + + for _, route := range testdata.Routes("testdata/github.txt") { + router.HandleFunc(route.Method, route.Path, func(w http.ResponseWriter, r *http.Request) { + w.Write(payload) + }) + } + + for range b.N { + router.ServeHTTP(response, request) + } + }) +}