@@ -2016,14 +2016,15 @@ func Test_AddRoute_MergeHandlers(t *testing.T) {
20162016}
20172017
20182018func Benchmark_App_RebuildTree_Parallel (b * testing.B ) {
2019- app := New ()
2020- registerDummyRoutes (app )
20212019 b .ReportAllocs ()
20222020 b .ResetTimer ()
20232021 b .RunParallel (func (pb * testing.PB ) {
2022+ // Each worker gets its own App instance to avoid data races on shared state
2023+ localApp := New ()
2024+ registerDummyRoutes (localApp )
20242025 for pb .Next () {
2025- app .routesRefreshed = true
2026- app .RebuildTree ()
2026+ localApp .routesRefreshed = true
2027+ localApp .RebuildTree ()
20272028 }
20282029 })
20292030}
@@ -2036,17 +2037,24 @@ func Benchmark_App_MethodNotAllowed_Parallel(b *testing.B) {
20362037 app .All ("/this/is/a/" , h )
20372038 app .Get ("/this/is/a/dummy/route/oke" , h )
20382039 appHandler := app .Handler ()
2039- c := & fasthttp.RequestCtx {}
2040- c .Request .Header .SetMethod ("DELETE" )
2041- c .URI ().SetPath ("/this/is/a/dummy/route/oke" )
20422040 b .RunParallel (func (pb * testing.PB ) {
2041+ // Each worker gets its own RequestCtx to avoid data races
2042+ c := & fasthttp.RequestCtx {}
2043+ c .Request .Header .SetMethod ("DELETE" )
2044+ c .URI ().SetPath ("/this/is/a/dummy/route/oke" )
20432045 for pb .Next () {
20442046 appHandler (c )
20452047 }
20462048 })
2047- require .Equal (b , 405 , c .Response .StatusCode ())
2048- require .Equal (b , MethodGet + ", " + MethodHead , string (c .Response .Header .Peek ("Allow" )))
2049- require .Equal (b , utils .StatusMessage (StatusMethodNotAllowed ), string (c .Response .Body ()))
2049+
2050+ // Single-threaded verification on a fresh context to preserve correctness checks
2051+ verifyCtx := & fasthttp.RequestCtx {}
2052+ verifyCtx .Request .Header .SetMethod ("DELETE" )
2053+ verifyCtx .URI ().SetPath ("/this/is/a/dummy/route/oke" )
2054+ appHandler (verifyCtx )
2055+ require .Equal (b , 405 , verifyCtx .Response .StatusCode ())
2056+ require .Equal (b , MethodGet + ", " + MethodHead , string (verifyCtx .Response .Header .Peek ("Allow" )))
2057+ require .Equal (b , utils .StatusMessage (StatusMethodNotAllowed ), string (verifyCtx .Response .Body ()))
20502058}
20512059
20522060func Benchmark_Router_NotFound_Parallel (b * testing.B ) {
@@ -2158,6 +2166,7 @@ func Benchmark_Router_Next_Parallel(b *testing.B) {
21582166 c := acquireDefaultCtxForRouterBenchmark (b , app , request )
21592167 for pb .Next () {
21602168 c .indexRoute = - 1
2169+ //nolint:errcheck // Benchmark hot path - error checked in verification
21612170 _ , _ = app .next (c )
21622171 }
21632172 })
@@ -2192,20 +2201,24 @@ func Benchmark_Router_Next_Default_Immutable_Parallel(b *testing.B) {
21922201}
21932202
21942203func Benchmark_Route_Match_Parallel (b * testing.B ) {
2195- var match bool
2196- var params [maxParams ]string
21972204 parsed := parseRoute ("/user/keys/:id" )
21982205 route := & Route {use : false , root : false , star : false , routeParser : parsed , Params : parsed .params , path : "/user/keys/:id" , Path : "/user/keys/:id" , Method : "DELETE" }
21992206 route .Handlers = append (route .Handlers , func (_ Ctx ) error {
22002207 return nil
22012208 })
22022209 b .RunParallel (func (pb * testing.PB ) {
2210+ // Each worker gets its own local variables to avoid data races
2211+ var params [maxParams ]string
22032212 for pb .Next () {
2204- match = route .match ("/user/keys/1337" , "/user/keys/1337" , & params )
2213+ _ = route .match ("/user/keys/1337" , "/user/keys/1337" , & params )
22052214 }
22062215 })
2216+
2217+ // Single-threaded verification to preserve correctness checks
2218+ var verifyParams [maxParams ]string
2219+ match := route .match ("/user/keys/1337" , "/user/keys/1337" , & verifyParams )
22072220 require .True (b , match )
2208- require .Equal (b , []string {"1337" }, params [0 :len (parsed .params )])
2221+ require .Equal (b , []string {"1337" }, verifyParams [0 :len (parsed .params )])
22092222}
22102223
22112224func Benchmark_Route_Match_Star_Parallel (b * testing.B ) {
@@ -2295,20 +2308,28 @@ func Benchmark_Router_GitHub_API_Parallel(b *testing.B) {
22952308 app := New ()
22962309 registerDummyRoutes (app )
22972310 app .startupProcess ()
2298- c := & fasthttp.RequestCtx {}
2299- var match bool
2300- var err error
23012311 b .ResetTimer ()
23022312 for i := range routesFixture .TestRoutes {
23032313 b .RunParallel (func (pb * testing.PB ) {
2314+ // Each worker gets its own RequestCtx and local variables to avoid data races
2315+ c := & fasthttp.RequestCtx {}
23042316 c .Request .Header .SetMethod (routesFixture .TestRoutes [i ].Method )
23052317 for pb .Next () {
23062318 c .URI ().SetPath (routesFixture .TestRoutes [i ].Path )
23072319 ctx := acquireDefaultCtxForRouterBenchmark (b , app , c )
2308- match , err = app .next (ctx )
2320+ //nolint:errcheck // Benchmark hot path - error checked in verification
2321+ _ , _ = app .next (ctx )
23092322 app .ReleaseCtx (ctx )
23102323 }
23112324 })
2325+
2326+ // Single-threaded verification on a fresh context to preserve correctness checks
2327+ verifyC := & fasthttp.RequestCtx {}
2328+ verifyC .Request .Header .SetMethod (routesFixture .TestRoutes [i ].Method )
2329+ verifyC .URI ().SetPath (routesFixture .TestRoutes [i ].Path )
2330+ verifyCtx := acquireDefaultCtxForRouterBenchmark (b , app , verifyC )
2331+ match , err := app .next (verifyCtx )
2332+ app .ReleaseCtx (verifyCtx )
23122333 require .NoError (b , err )
23132334 require .True (b , match )
23142335 }
0 commit comments