Skip to content
This repository was archived by the owner on May 17, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added air.test
Binary file not shown.
101 changes: 101 additions & 0 deletions airbench.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package air

import (
"fmt"
"io"
"log"
"net/http"
"runtime"
"time"
)

type route struct {
method string
path string
}

var nullLogger *log.Logger
var loadTestHandler = false

type mockResponseWriter struct{}

func (m *mockResponseWriter) Header() (h http.Header) {
return http.Header{}
}

func (m *mockResponseWriter) Write(p []byte) (n int, err error) {
return len(p), nil
}

func (m *mockResponseWriter) WriteString(s string) (n int, err error) {
return len(s), nil
}
func httpHandlerFunc(w http.ResponseWriter, r *http.Request) {}

func httpHandlerFuncTest(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, r.RequestURI)
}
func (m *mockResponseWriter) WriteHeader(int) {}

// func main() {
// fmt.Println("Usage: go test -bench=.")
// os.Exit(1)
// }
func airHandler(req *Request, res *Response) error {
var msg struct {
Name string `json:"user"`
}
msg.Name = "Hello"
return res.WriteJSON(msg)
}

func airHandlerWrite(req *Request, res *Response) error {
var msg struct {
Name string `json:"user"`
}
msg.Name = "Hello"
return res.WriteJSON(msg)
}
func airHandlerTest(req *Request, res *Response) error {
return res.WriteString(req.Path)
}
func airMiddleware(next Handler) Handler {
return func(req *Request, res *Response) error {
start := time.Now()
err := next(req, res)
responseTime := time.Since(start)

// Write it to the log
fmt.Println(responseTime)

// Make sure to pass the error back!
return err
}
}
func init() {
runtime.GOMAXPROCS(1)

// makes logging 'webscale' (ignores them)
log.SetOutput(new(mockResponseWriter))
nullLogger = log.New(new(mockResponseWriter), "", 0)
}
func loadAirSingle(method, path string, h Handler) *Air {

app := New()
switch method {
case "GET":
app.GET(path, h, airMiddleware)
case "POST":
app.POST(path, h, airMiddleware)
case "PUT":
app.PUT(path, h, airMiddleware)
case "PATCH":
app.PATCH(path, h, airMiddleware)
case "DELETE":
app.DELETE(path, h, airMiddleware)
default:
panic("Unknow HTTP method: " + method)
}

return app
}
104 changes: 104 additions & 0 deletions bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package air

import (
"net/http"
"os"
"regexp"
"runtime"
"strings"
"testing"
)

var benchRe *regexp.Regexp

const fiveColon = "/:a/:b/:c/:d/:e"
const fiveBrace = "/{a}/{b}/{c}/{d}/{e}"
const fiveRoute = "/test/test/test/test/test"

const twentyColon = "/:a/:b/:c/:d/:e/:f/:g/:h/:i/:j/:k/:l/:m/:n/:o/:p/:q/:r/:s/:t"
const twentyBrace = "/{a}/{b}/{c}/{d}/{e}/{f}/{g}/{h}/{i}/{j}/{k}/{l}/{m}/{n}/{o}/{p}/{q}/{r}/{s}/{t}"
const twentyRoute = "/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t"

func isTested(name string) bool {
if benchRe == nil {
// Get -test.bench flag value (not accessible via flag package)
bench := ""
for _, arg := range os.Args {
if strings.HasPrefix(arg, "-test.bench=") {
// ignore the benchmark name after an underscore
bench = strings.SplitN(arg[12:], "_", 2)[0]
break
}
}

// Compile RegExp to match Benchmark names
var err error
benchRe, err = regexp.Compile(bench)
if err != nil {
panic(err.Error())
}
}
return benchRe.MatchString(name)
}

func calcMem(name string, load func()) {
if !isTested(name) {
return
}

m := new(runtime.MemStats)

// before
runtime.GC()
runtime.ReadMemStats(m)
before := m.HeapAlloc

load()

// after
runtime.GC()
runtime.ReadMemStats(m)
after := m.HeapAlloc
println(" "+name+":", after-before, "Bytes")
}

func benchRequest(b *testing.B, router *Air, r *http.Request) {
w := new(mockResponseWriter)
u := r.URL
rq := u.RawQuery
r.RequestURI = u.RequestURI()

b.ReportAllocs()
b.ResetTimer()
// http.HandlerFunc()
for i := 0; i < b.N; i++ {
u.RawQuery = rq
router.server.ServeHTTP(w, r)
// WrapHTTPHandler(http.Handler(r))
}
}
func benchRoutes(b *testing.B, router *Air, routes []route) {
w := new(mockResponseWriter)
r, _ := http.NewRequest("GET", "/", nil)
u := r.URL
rq := u.RawQuery

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
for _, route := range routes {
r.Method = route.method
r.RequestURI = route.path
u.Path = route.path
u.RawQuery = rq
router.server.ServeHTTP(w, r)
}
}
}
func BenchmarkAir_Error404(b *testing.B) {
router := loadAirSingle("GET", "/user/:name", airHandler)

r, _ := http.NewRequest("GET", "/user/gordon", nil)
benchRequest(b, router, r)
}
Binary file added cpu.out
Binary file not shown.
Binary file added cpuprofile-week-7.out
Binary file not shown.
Binary file added cpuprofile-week-9.out
Binary file not shown.
Binary file added cpuprofile.out
Binary file not shown.
Binary file added mem.out
Binary file not shown.
Binary file added memprofile.out
Binary file not shown.