Implement benchmarks
This commit is contained in:
parent
b391f06121
commit
801ef570e2
55
README.md
55
README.md
|
@ -1,3 +1,56 @@
|
||||||
# Router
|
# Router
|
||||||
|
|
||||||
A radix-tree based no-allocation router in Go.
|
A radix-tree based no-allocation router in Go. All credit to Eduard Urbach for his incredible work.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Efficient lookup
|
||||||
|
- Generic data structure
|
||||||
|
- Zero dependencies
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```shell
|
||||||
|
go get git.sharkk.net/Go/Router
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
router := router.New[string]()
|
||||||
|
|
||||||
|
// Static routes
|
||||||
|
router.Add("GET", "/hello", "...")
|
||||||
|
router.Add("GET", "/world", "...")
|
||||||
|
|
||||||
|
// Parameter routes
|
||||||
|
router.Add("GET", "/users/:id", "...")
|
||||||
|
router.Add("GET", "/users/:id/comments", "...")
|
||||||
|
|
||||||
|
// Wildcard routes
|
||||||
|
router.Add("GET", "/images/*path", "...")
|
||||||
|
|
||||||
|
// Simple lookup
|
||||||
|
data, params := router.Lookup("GET", "/users/42")
|
||||||
|
fmt.Println(data, params)
|
||||||
|
|
||||||
|
// Efficient lookup
|
||||||
|
data := router.LookupNoAlloc("GET", "/users/42", func(key string, value string) {
|
||||||
|
fmt.Println(key, value)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Benchmarks
|
||||||
|
```
|
||||||
|
goos: linux
|
||||||
|
goarch: amd64
|
||||||
|
pkg: git.sharkk.net/Go/Router/tests
|
||||||
|
cpu: AMD Ryzen 9 7950X 16-Core Processor
|
||||||
|
BenchmarkBlog/Len1-Param0-32 384992013 3.337 ns/op 0 B/op 0 allocs/op
|
||||||
|
BenchmarkBlog/Len1-Param1-32 199599014 6.021 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-Param2-32 256228226 4.673 ns/op 0 B/op 0 allocs/op
|
||||||
|
PASS
|
||||||
|
ok git.sharkk.net/Go/Router/tests 8.410s
|
||||||
|
```
|
106
tests/benchmark_test.go
Normal file
106
tests/benchmark_test.go
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
package router_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
router "git.sharkk.net/Go/Router"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkBlog(b *testing.B) {
|
||||||
|
routes := routes("blog.txt")
|
||||||
|
r := router.New[string]()
|
||||||
|
|
||||||
|
for _, route := range routes {
|
||||||
|
r.Add(route.Method, route.Path, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Run("Len1-Param0", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.LookupNoAlloc("GET", "/", noop)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("Len1-Param1", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.LookupNoAlloc("GET", "/:id", noop)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkGithub(b *testing.B) {
|
||||||
|
routes := routes("routes.txt")
|
||||||
|
r := router.New[string]()
|
||||||
|
|
||||||
|
for _, route := range routes {
|
||||||
|
r.Add(route.Method, route.Path, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Run("Len7-Param0", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.LookupNoAlloc("GET", "/issues", noop)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("Len7-Param1", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.LookupNoAlloc("GET", "/gists/:id", noop)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("Len7-Param2", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
r.LookupNoAlloc("GET", "/repos/:owner/:repo/issues", noop)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Route represents a single line in the router test file.
|
||||||
|
type Route struct {
|
||||||
|
Method string
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Routes loads all routes from a text file.
|
||||||
|
func routes(fileName string) []Route {
|
||||||
|
var routes []Route
|
||||||
|
|
||||||
|
for line := range lines(fileName) {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
parts := strings.Split(line, " ")
|
||||||
|
routes = append(routes, Route{
|
||||||
|
Method: parts[0],
|
||||||
|
Path: parts[1],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lines is a utility function to easily read every line in a text file.
|
||||||
|
func lines(fileName string) <-chan string {
|
||||||
|
lines := make(chan string)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(lines)
|
||||||
|
file, err := os.Open(fileName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
lines <- scanner.Text()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
// noop serves as an empty addParameter function.
|
||||||
|
func noop(string, string) {}
|
4
tests/blog.txt
Normal file
4
tests/blog.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
GET /
|
||||||
|
GET /:slug
|
||||||
|
GET /tags
|
||||||
|
GET /tag/:tag
|
203
tests/github.txt
Normal file
203
tests/github.txt
Normal file
|
@ -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
|
Loading…
Reference in New Issue
Block a user