Fix github uri bench, update comments and benchmark results
This commit is contained in:
parent
801ef570e2
commit
5d8a722be6
24
README.md
24
README.md
|
@ -42,15 +42,17 @@ data := router.LookupNoAlloc("GET", "/users/42", func(key string, value string)
|
||||||
|
|
||||||
## Benchmarks
|
## Benchmarks
|
||||||
```
|
```
|
||||||
goos: linux
|
cpu: AMD Ryzen 9 7950X 16-Core Processor
|
||||||
goarch: amd64
|
|
||||||
pkg: git.sharkk.net/Go/Router/tests
|
BenchmarkBlog/Len1-Params0-32 268391120 4.461 ns/op 0 B/op 0 allocs/op
|
||||||
cpu: AMD Ryzen 9 7950X 16-Core Processor
|
BenchmarkBlog/Len1-Params0-NoAlloc-32 383737024 3.123 ns/op 0 B/op 0 allocs/op
|
||||||
BenchmarkBlog/Len1-Param0-32 384992013 3.337 ns/op 0 B/op 0 allocs/op
|
BenchmarkBlog/Len1-Param1-32 23690427 47.85 ns/op 32 B/op 1 allocs/op
|
||||||
BenchmarkBlog/Len1-Param1-32 199599014 6.021 ns/op 0 B/op 0 allocs/op
|
BenchmarkBlog/Len1-Param1-NoAlloc-32 248275540 4.913 ns/op 0 B/op 0 allocs/op
|
||||||
BenchmarkGithub/Len7-Param0-32 256332994 4.678 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkGithub/Len7-Param1-32 269038417 4.455 ns/op 0 B/op 0 allocs/op
|
BenchmarkGithub/Len7-Params0-32 148926122 8.043 ns/op 0 B/op 0 allocs/op
|
||||||
BenchmarkGithub/Len7-Param2-32 256228226 4.673 ns/op 0 B/op 0 allocs/op
|
BenchmarkGithub/Len7-Params0-NoAlloc-32 168011829 7.153 ns/op 0 B/op 0 allocs/op
|
||||||
PASS
|
BenchmarkGithub/Len7-Params1-32 22188592 47.25 ns/op 32 B/op 1 allocs/op
|
||||||
ok git.sharkk.net/Go/Router/tests 8.410s
|
BenchmarkGithub/Len7-Params1-NoAlloc-32 100000000 11.29 ns/op 0 B/op 0 allocs/op
|
||||||
|
BenchmarkGithub/Len7-Params3-32 10181496 111.3 ns/op 96 B/op 2 allocs/op
|
||||||
|
BenchmarkGithub/Len7-Params3-NoAlloc-32 46369563 25.54 ns/op 0 B/op 0 allocs/op
|
||||||
```
|
```
|
13
Router.go
13
Router.go
|
@ -1,6 +1,5 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
// Router is a high-performance router.
|
|
||||||
type Router[T any] struct {
|
type Router[T any] struct {
|
||||||
get Tree[T]
|
get Tree[T]
|
||||||
post Tree[T]
|
post Tree[T]
|
||||||
|
@ -13,18 +12,18 @@ type Router[T any] struct {
|
||||||
options Tree[T]
|
options Tree[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new router containing trees for every HTTP method.
|
// Creates a new router containing trees for every HTTP method.
|
||||||
func New[T any]() *Router[T] {
|
func New[T any]() *Router[T] {
|
||||||
return &Router[T]{}
|
return &Router[T]{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add registers a new handler for the given method and path.
|
// Registers a new handler for the given method and path.
|
||||||
func (router *Router[T]) Add(method string, path string, handler T) {
|
func (router *Router[T]) Add(method string, path string, handler T) {
|
||||||
tree := router.selectTree(method)
|
tree := router.selectTree(method)
|
||||||
tree.Add(path, handler)
|
tree.Add(path, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup finds the handler and parameters for the given route.
|
// Finds the handler and parameters for the given route.
|
||||||
func (router *Router[T]) Lookup(method string, path string) (T, []Parameter) {
|
func (router *Router[T]) Lookup(method string, path string) (T, []Parameter) {
|
||||||
if method[0] == 'G' {
|
if method[0] == 'G' {
|
||||||
return router.get.Lookup(path)
|
return router.get.Lookup(path)
|
||||||
|
@ -34,7 +33,7 @@ func (router *Router[T]) Lookup(method string, path string) (T, []Parameter) {
|
||||||
return tree.Lookup(path)
|
return tree.Lookup(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupNoAlloc finds the handler and parameters for the given route without using any memory allocations.
|
// Finds the handler and parameters for the given route without using any memory allocations.
|
||||||
func (router *Router[T]) LookupNoAlloc(method string, path string, addParameter func(string, string)) T {
|
func (router *Router[T]) LookupNoAlloc(method string, path string, addParameter func(string, string)) T {
|
||||||
if method[0] == 'G' {
|
if method[0] == 'G' {
|
||||||
return router.get.LookupNoAlloc(path, addParameter)
|
return router.get.LookupNoAlloc(path, addParameter)
|
||||||
|
@ -44,7 +43,7 @@ func (router *Router[T]) LookupNoAlloc(method string, path string, addParameter
|
||||||
return tree.LookupNoAlloc(path, addParameter)
|
return tree.LookupNoAlloc(path, addParameter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map traverses all trees and calls the given function on every node.
|
// Traverses all trees and calls the given function on every node.
|
||||||
func (router *Router[T]) Map(transform func(T) T) {
|
func (router *Router[T]) Map(transform func(T) T) {
|
||||||
router.get.Map(transform)
|
router.get.Map(transform)
|
||||||
router.post.Map(transform)
|
router.post.Map(transform)
|
||||||
|
@ -57,7 +56,7 @@ func (router *Router[T]) Map(transform func(T) T) {
|
||||||
router.options.Map(transform)
|
router.options.Map(transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
// selectTree returns the tree by the given HTTP method.
|
// Returns the tree by the given HTTP method.
|
||||||
func (router *Router[T]) selectTree(method string) *Tree[T] {
|
func (router *Router[T]) selectTree(method string) *Tree[T] {
|
||||||
switch method {
|
switch method {
|
||||||
case "GET":
|
case "GET":
|
||||||
|
|
2
Tree.go
2
Tree.go
|
@ -89,7 +89,7 @@ func (tree *Tree[T]) Lookup(path string) (T, []Parameter) {
|
||||||
return data, params
|
return data, params
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupNoAlloc finds the data for the given path without using any memory allocations.
|
// Finds the data for the given path without using any memory allocations.
|
||||||
func (tree *Tree[T]) LookupNoAlloc(path string, addParameter func(key string, value string)) T {
|
func (tree *Tree[T]) LookupNoAlloc(path string, addParameter func(key string, value string)) T {
|
||||||
var (
|
var (
|
||||||
i uint
|
i uint
|
||||||
|
|
|
@ -17,13 +17,25 @@ func BenchmarkBlog(b *testing.B) {
|
||||||
r.Add(route.Method, route.Path, "")
|
r.Add(route.Method, route.Path, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Run("Len1-Param0", func(b *testing.B) {
|
b.Run("Len1-Params0", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Lookup("GET", "/")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("Len1-Params0-NoAlloc", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
r.LookupNoAlloc("GET", "/", noop)
|
r.LookupNoAlloc("GET", "/", noop)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
b.Run("Len1-Param1", func(b *testing.B) {
|
b.Run("Len1-Param1", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Lookup("GET", "/:id")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("Len1-Param1-NoAlloc", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
r.LookupNoAlloc("GET", "/:id", noop)
|
r.LookupNoAlloc("GET", "/:id", noop)
|
||||||
}
|
}
|
||||||
|
@ -31,26 +43,44 @@ func BenchmarkBlog(b *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkGithub(b *testing.B) {
|
func BenchmarkGithub(b *testing.B) {
|
||||||
routes := routes("routes.txt")
|
routes := routes("github.txt")
|
||||||
r := router.New[string]()
|
r := router.New[string]()
|
||||||
|
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
r.Add(route.Method, route.Path, "")
|
r.Add(route.Method, route.Path, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Run("Len7-Param0", func(b *testing.B) {
|
b.Run("Len7-Params0", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Lookup("GET", "/issues")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("Len7-Params0-NoAlloc", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
r.LookupNoAlloc("GET", "/issues", noop)
|
r.LookupNoAlloc("GET", "/issues", noop)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
b.Run("Len7-Param1", func(b *testing.B) {
|
b.Run("Len7-Params1", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Lookup("GET", "/gists/:id")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("Len7-Params1-NoAlloc", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
r.LookupNoAlloc("GET", "/gists/:id", noop)
|
r.LookupNoAlloc("GET", "/gists/:id", noop)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
b.Run("Len7-Param2", func(b *testing.B) {
|
b.Run("Len7-Params3", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.Lookup("GET", "/repos/:owner/:repo/issues")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("Len7-Params3-NoAlloc", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
r.LookupNoAlloc("GET", "/repos/:owner/:repo/issues", noop)
|
r.LookupNoAlloc("GET", "/repos/:owner/:repo/issues", noop)
|
||||||
}
|
}
|
||||||
|
@ -63,7 +93,7 @@ type Route struct {
|
||||||
Path string
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routes loads all routes from a text file.
|
// Loads all routes from a text file.
|
||||||
func routes(fileName string) []Route {
|
func routes(fileName string) []Route {
|
||||||
var routes []Route
|
var routes []Route
|
||||||
|
|
||||||
|
@ -79,7 +109,7 @@ func routes(fileName string) []Route {
|
||||||
return routes
|
return routes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lines is a utility function to easily read every line in a text file.
|
// Easily read every line in a text file.
|
||||||
func lines(fileName string) <-chan string {
|
func lines(fileName string) <-chan string {
|
||||||
lines := make(chan string)
|
lines := make(chan string)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user