Browse Source

Use sync.Pool for go1.3 and up

This has the additional benefit of removing the need for a go1.3 branch.
Carl Jackson 11 years ago
parent
commit
ab8aa1f6d8
5 changed files with 65 additions and 23 deletions
  1. +31
    -0
      web/chanpool.go
  2. +24
    -0
      web/cpool.go
  3. +7
    -20
      web/middleware.go
  4. +2
    -2
      web/middleware_test.go
  5. +1
    -1
      web/mux.go

+ 31
- 0
web/chanpool.go View File

@ -0,0 +1,31 @@
// +build !go1.3
package web
// This is an alternate implementation of Go 1.3's sync.Pool.
// Maximum size of the pool of spare middleware stacks
const cPoolSize = 32
type cPool chan *cStack
func makeCPool() *cPool {
var p cPool = make(chan *cStack, cPoolSize)
return &p
}
func (c cPool) alloc() *cStack {
select {
case cs := <-c:
return cs
default:
return nil
}
}
func (c cPool) release(cs *cStack) {
select {
case c <- cs:
default:
}
}

+ 24
- 0
web/cpool.go View File

@ -0,0 +1,24 @@
// +build go1.3
package web
import "sync"
type cPool sync.Pool
func makeCPool() *cPool {
return &cPool{}
}
func (c *cPool) alloc() *cStack {
cs := (*sync.Pool)(c).Get()
if cs == nil {
return nil
} else {
return cs.(*cStack)
}
}
func (c *cPool) release(cs *cStack) {
(*sync.Pool)(c).Put(cs)
}

+ 7
- 20
web/middleware.go View File

@ -7,9 +7,6 @@ import (
"sync" "sync"
) )
// Maximum size of the pool of spare middleware stacks
const mPoolSize = 32
type mLayer struct { type mLayer struct {
fn func(*C, http.Handler) http.Handler fn func(*C, http.Handler) http.Handler
orig interface{} orig interface{}
@ -18,7 +15,7 @@ type mLayer struct {
type mStack struct { type mStack struct {
lock sync.Mutex lock sync.Mutex
stack []mLayer stack []mLayer
pool chan *cStack
pool *cPool
router internalRouter router internalRouter
} }
@ -46,7 +43,7 @@ cStack on the floor.
type cStack struct { type cStack struct {
C C
m http.Handler m http.Handler
pool chan *cStack
pool *cPool
} }
func (s *cStack) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (s *cStack) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -86,7 +83,7 @@ func (m *mStack) findLayer(l interface{}) int {
} }
func (m *mStack) invalidate() { func (m *mStack) invalidate() {
m.pool = make(chan *cStack, mPoolSize)
m.pool = makeCPool()
} }
func (m *mStack) newStack() *cStack { func (m *mStack) newStack() *cStack {
@ -112,16 +109,8 @@ func (m *mStack) alloc() *cStack {
// sync/atomic, but for now I happen to know that on all the // sync/atomic, but for now I happen to know that on all the
// architectures I care about it happens to be atomic. // architectures I care about it happens to be atomic.
p := m.pool p := m.pool
var cs *cStack
select {
case cs = <-p:
// This can happen if we race against an invalidation. It's
// completely peaceful, so long as we assume we can grab a cStack before
// our stack blows out.
if cs == nil {
return m.alloc()
}
default:
cs := p.alloc()
if cs == nil {
cs = m.newStack() cs = m.newStack()
} }
@ -134,10 +123,8 @@ func (m *mStack) release(cs *cStack) {
if cs.pool != m.pool { if cs.pool != m.pool {
return return
} }
select {
case cs.pool <- cs:
default:
}
cs.pool.release(cs)
cs.pool = nil
} }
// Append the given middleware to the middleware stack. See the documentation // Append the given middleware to the middleware stack. See the documentation


+ 2
- 2
web/middleware_test.go View File

@ -19,7 +19,7 @@ func makeStack(ch chan string) *mStack {
} }
return &mStack{ return &mStack{
stack: make([]mLayer, 0), stack: make([]mLayer, 0),
pool: make(chan *cStack, mPoolSize),
pool: makeCPool(),
router: iRouter(router), router: iRouter(router),
} }
} }
@ -215,7 +215,7 @@ func TestContext(t *testing.T) {
} }
st := mStack{ st := mStack{
stack: make([]mLayer, 0), stack: make([]mLayer, 0),
pool: make(chan *cStack, mPoolSize),
pool: makeCPool(),
router: iRouter(router), router: iRouter(router),
} }
st.Use(func(c *C, h http.Handler) http.Handler { st.Use(func(c *C, h http.Handler) http.Handler {


+ 1
- 1
web/mux.go View File

@ -61,7 +61,7 @@ func New() *Mux {
mux := Mux{ mux := Mux{
mStack: mStack{ mStack: mStack{
stack: make([]mLayer, 0), stack: make([]mLayer, 0),
pool: make(chan *cStack, mPoolSize),
pool: makeCPool(),
}, },
router: router{ router: router{
routes: make([]route, 0), routes: make([]route, 0),


Loading…
Cancel
Save