Skip to content

Commit 8e7b59f

Browse files
committed
Create a global pool to share contexts between all routes
1 parent 1f927a8 commit 8e7b59f

File tree

2 files changed

+22
-20
lines changed

2 files changed

+22
-20
lines changed

Diff for: context.go

+18-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"net/http"
66
"strings"
7+
"sync"
78
)
89

910
// URLParam returns the url parameter from a http.Request object.
@@ -39,17 +40,29 @@ var (
3940
RouteCtxKey = &contextKey{"RouteContext"}
4041
)
4142

43+
var contextPool = sync.Pool{
44+
New: func() interface{} {
45+
return NewRouteContext()
46+
},
47+
}
48+
49+
func GetRouteContext(mx *Mux) *Context {
50+
rctx := contextPool.Get().(*Context)
51+
rctx.Routes = mx
52+
return rctx
53+
}
54+
55+
func PutRouteContext(rctx *Context) {
56+
rctx.Reset()
57+
contextPool.Put(rctx)
58+
}
59+
4260
// Context is the default routing context set on the root node of a
4361
// request context to track route patterns, URL parameters and
4462
// an optional routing path.
4563
type Context struct {
4664
Routes Routes
4765

48-
// parentCtx is the parent of this one, for using Context as a
49-
// context.Context directly. This is an optimization that saves
50-
// 1 allocation.
51-
parentCtx context.Context
52-
5366
// Routing path/method override used during the route search.
5467
// See Mux#routeHTTP method.
5568
RoutePath string
@@ -92,7 +105,6 @@ func (x *Context) Reset() {
92105
x.routeParams.Values = x.routeParams.Values[:0]
93106
x.methodNotAllowed = false
94107
x.methodsAllowed = x.methodsAllowed[:0]
95-
x.parentCtx = nil
96108
}
97109

98110
// URLParam returns the corresponding URL parameter value from the request

Diff for: mux.go

+4-14
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"net/http"
77
"strings"
8-
"sync"
98
)
109

1110
var _ Router = &Mux{}
@@ -33,9 +32,6 @@ type Mux struct {
3332
// to a parent mux
3433
parent *Mux
3534

36-
// Routing context pool
37-
pool *sync.Pool
38-
3935
// Custom route not found handler
4036
notFoundHandler http.HandlerFunc
4137

@@ -50,10 +46,7 @@ type Mux struct {
5046
// NewMux returns a newly initialized Mux object that implements the Router
5147
// interface.
5248
func NewMux() *Mux {
53-
mux := &Mux{tree: &node{}, pool: &sync.Pool{}}
54-
mux.pool.New = func() interface{} {
55-
return NewRouteContext()
56-
}
49+
mux := &Mux{tree: &node{}}
5750
return mux
5851
}
5952

@@ -78,17 +71,14 @@ func (mx *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
7871
// mx.handler that is comprised of mx.middlewares + mx.routeHTTP.
7972
// Once the request is finished, reset the routing context and put it back
8073
// into the pool for reuse from another request.
81-
rctx = mx.pool.Get().(*Context)
82-
rctx.Reset()
83-
rctx.Routes = mx
84-
rctx.parentCtx = r.Context()
74+
rctx = GetRouteContext(mx)
75+
defer PutRouteContext(rctx)
8576

8677
// NOTE: r.WithContext() causes 2 allocations and context.WithValue() causes 1 allocation
8778
r = r.WithContext(context.WithValue(r.Context(), RouteCtxKey, rctx))
8879

8980
// Serve the request and once its done, put the request context back in the sync pool
9081
mx.handler.ServeHTTP(w, r)
91-
mx.pool.Put(rctx)
9282
}
9383

9484
// Use appends a middleware handler to the Mux middleware stack.
@@ -255,7 +245,7 @@ func (mx *Mux) With(middlewares ...func(http.Handler) http.Handler) Router {
255245
mws = append(mws, middlewares...)
256246

257247
im := &Mux{
258-
pool: mx.pool, inline: true, parent: mx, tree: mx.tree, middlewares: mws,
248+
inline: true, parent: mx, tree: mx.tree, middlewares: mws,
259249
notFoundHandler: mx.notFoundHandler, methodNotAllowedHandler: mx.methodNotAllowedHandler,
260250
}
261251

0 commit comments

Comments
 (0)