Implement benchmarks
This commit is contained in:
parent
b391f06121
commit
801ef570e2
55
README.md
55
README.md
|
@ -1,3 +1,56 @@
|
|||
# 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