pip compatible server to serve Python packages out of GitHub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

166 lines
3.2 KiB

// +build go1.3
package web
import (
"crypto/rand"
"encoding/base64"
mrand "math/rand"
"net/http"
"testing"
)
/*
The core benchmarks here are based on cypriss's mux benchmarks, which can be
found here:
https://github.com/cypriss/golang-mux-benchmark
They happen to play very well into Goji's router's strengths.
*/
type nilRouter struct{}
var helloWorld = []byte("Hello world!\n")
func (_ nilRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write(helloWorld)
}
type nilResponse struct{}
func (_ nilResponse) Write(buf []byte) (int, error) {
return len(buf), nil
}
func (_ nilResponse) Header() http.Header {
return nil
}
func (_ nilResponse) WriteHeader(code int) {
}
func trivialMiddleware(h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
var w nilResponse
func addRoutes(m *Mux, prefix string) {
m.Get(prefix, nilRouter{})
m.Post(prefix, nilRouter{})
m.Get(prefix+"/:id", nilRouter{})
m.Put(prefix+"/:id", nilRouter{})
m.Delete(prefix+"/:id", nilRouter{})
}
func randString() string {
var buf [6]byte
rand.Reader.Read(buf[:])
return base64.URLEncoding.EncodeToString(buf[:])
}
func genPrefixes(n int) []string {
p := make([]string, n)
for i := range p {
p[i] = "/" + randString()
}
return p
}
func genRequests(prefixes []string) []*http.Request {
rs := make([]*http.Request, 5*len(prefixes))
for i, prefix := range prefixes {
rs[5*i+0], _ = http.NewRequest("GET", prefix, nil)
rs[5*i+1], _ = http.NewRequest("POST", prefix, nil)
rs[5*i+2], _ = http.NewRequest("GET", prefix+"/foo", nil)
rs[5*i+3], _ = http.NewRequest("PUT", prefix+"/foo", nil)
rs[5*i+4], _ = http.NewRequest("DELETE", prefix+"/foo", nil)
}
return rs
}
func permuteRequests(reqs []*http.Request) []*http.Request {
out := make([]*http.Request, len(reqs))
perm := mrand.Perm(len(reqs))
for i, req := range reqs {
out[perm[i]] = req
}
return out
}
func benchN(b *testing.B, n int) {
m := New()
prefixes := genPrefixes(n)
for _, prefix := range prefixes {
addRoutes(m, prefix)
}
m.Compile()
reqs := permuteRequests(genRequests(prefixes))
b.ResetTimer()
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
i++
m.ServeHTTP(w, reqs[i%len(reqs)])
}
})
}
func benchM(b *testing.B, n int) {
m := New()
m.Get("/", nilRouter{})
for i := 0; i < n; i++ {
m.Use(trivialMiddleware)
}
r, _ := http.NewRequest("GET", "/", nil)
m.Compile()
b.ResetTimer()
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
m.ServeHTTP(w, r)
}
})
}
func BenchmarkStatic(b *testing.B) {
m := New()
m.Get("/", nilRouter{})
r, _ := http.NewRequest("GET", "/", nil)
m.Compile()
b.ResetTimer()
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
m.ServeHTTP(w, r)
}
})
}
func BenchmarkRoute5(b *testing.B) {
benchN(b, 1)
}
func BenchmarkRoute50(b *testing.B) {
benchN(b, 10)
}
func BenchmarkRoute500(b *testing.B) {
benchN(b, 100)
}
func BenchmarkRoute5000(b *testing.B) {
benchN(b, 1000)
}
func BenchmarkMiddleware1(b *testing.B) {
benchM(b, 1)
}
func BenchmarkMiddleware10(b *testing.B) {
benchM(b, 10)
}
func BenchmarkMiddleware100(b *testing.B) {
benchM(b, 100)
}