From 3e4033673eb26f63e1b38b3870afc8e1fdc31469 Mon Sep 17 00:00:00 2001 From: Manu Mtz-Almeida Date: Sun, 6 Jul 2014 21:09:23 +0200 Subject: [PATCH] Using sync.Pool instead of a channel --- gin.go | 80 ++++++++++++------------------------------------------- logger.go | 3 +-- 2 files changed, 18 insertions(+), 65 deletions(-) diff --git a/gin.go b/gin.go index 33459cbb..85216544 100644 --- a/gin.go +++ b/gin.go @@ -13,6 +13,7 @@ import ( "math" "net/http" "path" + "sync" ) const ( @@ -37,11 +38,6 @@ type ( ErrorMsgs []ErrorMsg - Config struct { - CacheSize int - Preallocated int - } - // Context is the most important part of gin. It allows us to pass variables between middleware, // manage the flow, validate the JSON of a request and render a JSON response for example. Context struct { @@ -68,19 +64,12 @@ type ( Engine struct { *RouterGroup HTMLTemplates *template.Template - cache chan *Context + cache sync.Pool handlers404 []HandlerFunc router *httprouter.Router } ) -var ( - DefaultConfig = Config{ - CacheSize: 1024, - Preallocated: 512, - } -) - // Allows type H to be used with xml.Marshal func (h H) MarshalXML(e *xml.Encoder, start xml.StartElement) error { start.Name = xml.Name{"", "map"} @@ -112,32 +101,19 @@ func (a ErrorMsgs) String() string { return buffer.String() } -func NewWithConfig(config Config) *Engine { - if config.CacheSize < 2 { - panic("CacheSize must be at least 2") - } - if config.Preallocated > config.CacheSize { - panic("Preallocated must be less or equal to CacheSize") - } +// Returns a new blank Engine instance without any middleware attached. +// The most basic configuration +func New() *Engine { engine := &Engine{} engine.RouterGroup = &RouterGroup{nil, "/", nil, engine} engine.router = httprouter.New() engine.router.NotFound = engine.handle404 - engine.cache = make(chan *Context, config.CacheSize) - - // Fill it with empty contexts - for i := 0; i < config.Preallocated; i++ { - engine.cache <- &Context{Engine: engine, Writer: &responseWriter{}} + engine.cache.New = func() interface{} { + return &Context{Engine: engine, Writer: &responseWriter{}} } return engine } -// Returns a new blank Engine instance without any middleware attached. -// The most basic configuration -func New() *Engine { - return NewWithConfig(DefaultConfig) -} - // Returns a Engine instance with the Logger and Recovery already attached. func Default() *Engine { engine := New() @@ -154,10 +130,6 @@ func (engine *Engine) NotFound404(handlers ...HandlerFunc) { engine.handlers404 = handlers } -func (engine *Engine) CacheStress() float32 { - return 1.0 - float32(len(engine.cache))/float32(cap(engine.cache)) -} - func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) { handlers := engine.combineHandlers(engine.handlers404) c := engine.createContext(w, req, nil, handlers) @@ -166,7 +138,7 @@ func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) { if !c.Writer.Written() { c.Data(404, MIMEPlain, []byte("404 page not found")) } - engine.reuseContext(c) + engine.cache.Put(c) } // ServeHTTP makes the router implement the http.Handler interface. @@ -185,32 +157,14 @@ func (engine *Engine) Run(addr string) { /************************************/ func (engine *Engine) createContext(w http.ResponseWriter, req *http.Request, params httprouter.Params, handlers []HandlerFunc) *Context { - select { - case c := <-engine.cache: - c.Writer.reset(w) - c.Req = req - c.Params = params - c.handlers = handlers - c.Keys = nil - c.index = -1 - return c - default: - return &Context{ - Writer: &responseWriter{w, -1, false}, - Req: req, - Params: params, - handlers: handlers, - index: -1, - Engine: engine, - } - } -} - -func (engine *Engine) reuseContext(c *Context) { - select { - case engine.cache <- c: - default: - } + c := engine.cache.Get().(*Context) + c.Writer.reset(w) + c.Req = req + c.Params = params + c.handlers = handlers + c.Keys = nil + c.index = -1 + return c } // Adds middlewares to the group, see example code in github. @@ -246,7 +200,7 @@ func (group *RouterGroup) Handle(method, p string, handlers []HandlerFunc) { group.engine.router.Handle(method, p, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) { c := group.engine.createContext(w, req, params, handlers) c.Next() - group.engine.reuseContext(c) + group.engine.cache.Put(c) }) } diff --git a/logger.go b/logger.go index 7bd87b70..3120cbe9 100644 --- a/logger.go +++ b/logger.go @@ -61,11 +61,10 @@ func Logger() HandlerFunc { color = red } latency := time.Since(start) - stdlogger.Printf("[GIN] %v |%s %3d %s| %12v | %3.1f%% | %s %4s %s\n", + stdlogger.Printf("[GIN] %v |%s %3d %s| %12v | %s %4s %s\n", time.Now().Format("2006/01/02 - 15:04:05"), color, c.Writer.Status(), reset, latency, - c.Engine.CacheStress()*100, requester, c.Req.Method, c.Req.URL.Path, )