package sux import ( "net/http" "net/http/httptest" "runtime" "testing" ) // BenchmarkParameterOperations benchmarks the new parameter handling func BenchmarkParameterOperations(b *testing.B) { params := Params{ keys: make([]string, 0, 4), values: make([]string, 0, 4), } b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { params.Set("id", "123") params.Set("name", "test") _ = params.Get("id") _ = params.Get("name") params.Reset() } } // BenchmarkPathParsing compares old vs new path parsing func BenchmarkPathParsingOld(b *testing.B) { path := "/users/123/posts/456/comments/789" b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { _ = parsePath(path) } } func BenchmarkPathParsingNew(b *testing.B) { path := "/users/123/posts/456/comments/789" b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { _ = parsePathZeroAlloc(path) } } // BenchmarkMemoryUsage tests memory efficiency under load func BenchmarkMemoryUsage(b *testing.B) { router := New() // Add routes with different patterns router.GET("/", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) router.GET("/users/:id", func(w http.ResponseWriter, r *http.Request) { params := ParamsFromContext(r) _ = params.Get("id") w.WriteHeader(http.StatusOK) }) router.GET("/files/*path", func(w http.ResponseWriter, r *http.Request) { params := ParamsFromContext(r) _ = params.Get("path") w.WriteHeader(http.StatusOK) }) requests := []struct { method string path string }{ {"GET", "/"}, {"GET", "/users/123"}, {"GET", "/files/docs/readme.txt"}, } var reqs []*http.Request for _, req := range requests { for i := 0; i < 100; i++ { reqs = append(reqs, httptest.NewRequest(req.method, req.path, nil)) } } b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { w := httptest.NewRecorder() router.ServeHTTP(w, reqs[i%len(reqs)]) } } // BenchmarkConcurrentAccess tests performance under high concurrency func BenchmarkConcurrentAccess(b *testing.B) { router := New() router.GET("/test/:id", func(w http.ResponseWriter, r *http.Request) { params := ParamsFromContext(r) _ = params.Get("id") w.WriteHeader(http.StatusOK) }) req := httptest.NewRequest("GET", "/test/123", nil) b.ResetTimer() b.ReportAllocs() b.RunParallel(func(pb *testing.PB) { for pb.Next() { w := httptest.NewRecorder() router.ServeHTTP(w, req) } }) } // BenchmarkGCPressure measures GC pressure from allocations func BenchmarkGCPressure(b *testing.B) { router := New() router.GET("/users/:id/posts/:postId", func(w http.ResponseWriter, r *http.Request) { params := ParamsFromContext(r) _ = params.Get("id") + params.Get("postId") w.WriteHeader(http.StatusOK) }) req := httptest.NewRequest("GET", "/users/123/posts/456", nil) // Force GC before benchmark runtime.GC() var m1, m2 runtime.MemStats runtime.ReadMemStats(&m1) b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { w := httptest.NewRecorder() router.ServeHTTP(w, req) } b.StopTimer() runtime.ReadMemStats(&m2) b.Logf("Allocs: %d, TotalAlloc: %d bytes", m2.Mallocs-m1.Mallocs, m2.TotalAlloc-m1.TotalAlloc) } // BenchmarkWildcardOptimization tests the wildcard parameter optimization func BenchmarkWildcardOptimization(b *testing.B) { router := New() router.GET("/files/*path", func(w http.ResponseWriter, r *http.Request) { params := ParamsFromContext(r) _ = params.Get("path") w.WriteHeader(http.StatusOK) }) // Test with varying path lengths paths := []string{ "/files/file.txt", "/files/docs/readme.txt", "/files/docs/api/v1/users.json", "/files/very/deep/nested/path/with/many/segments/file.txt", } var reqs []*http.Request for _, path := range paths { for i := 0; i < 25; i++ { reqs = append(reqs, httptest.NewRequest("GET", path, nil)) } } b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { w := httptest.NewRecorder() router.ServeHTTP(w, reqs[i%len(reqs)]) } } // BenchmarkPoolEfficiency tests the efficiency of our pooling strategy func BenchmarkPoolEfficiency(b *testing.B) { router := New() router.GET("/test/:param", func(w http.ResponseWriter, r *http.Request) { params := ParamsFromContext(r) _ = params.Get("param") w.WriteHeader(http.StatusOK) }) req := httptest.NewRequest("GET", "/test/value", nil) b.ResetTimer() b.ReportAllocs() // This should show minimal allocations due to pooling for i := 0; i < b.N; i++ { w := httptest.NewRecorder() router.ServeHTTP(w, req) } }