| @ -0,0 +1,125 @@ | |||
| package web | |||
| import ( | |||
| "crypto/rand" | |||
| "encoding/base64" | |||
| mrand "math/rand" | |||
| "net/http" | |||
| "testing" | |||
| "time" | |||
| ) | |||
| func init() { | |||
| mrand.Seed(time.Now().Unix()) | |||
| } | |||
| /* | |||
| 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) { | |||
| } | |||
| 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 testingMux(n int) (*Mux, []*http.Request) { | |||
| m := New() | |||
| prefixes := genPrefixes(n) | |||
| for _, prefix := range prefixes { | |||
| addRoutes(m, prefix) | |||
| } | |||
| reqs := permuteRequests(genRequests(prefixes)) | |||
| return m, reqs | |||
| } | |||
| func BenchmarkRoute5(b *testing.B) { | |||
| m, reqs := testingMux(1) | |||
| b.ResetTimer() | |||
| for i := 0; i < b.N; i++ { | |||
| m.ServeHTTP(w, reqs[i%len(reqs)]) | |||
| } | |||
| } | |||
| func BenchmarkRoute50(b *testing.B) { | |||
| m, reqs := testingMux(10) | |||
| b.ResetTimer() | |||
| for i := 0; i < b.N; i++ { | |||
| m.ServeHTTP(w, reqs[i%len(reqs)]) | |||
| } | |||
| } | |||
| func BenchmarkRoute500(b *testing.B) { | |||
| m, reqs := testingMux(100) | |||
| b.ResetTimer() | |||
| for i := 0; i < b.N; i++ { | |||
| m.ServeHTTP(w, reqs[i%len(reqs)]) | |||
| } | |||
| } | |||
| func BenchmarkRoute5000(b *testing.B) { | |||
| m, reqs := testingMux(1000) | |||
| b.ResetTimer() | |||
| for i := 0; i < b.N; i++ { | |||
| m.ServeHTTP(w, reqs[i%len(reqs)]) | |||
| } | |||
| } | |||