From 67b793fbc0698d8bd16d996a281634f810325f99 Mon Sep 17 00:00:00 2001 From: Carl Jackson Date: Wed, 18 Jun 2014 23:33:10 -0700 Subject: [PATCH] Don't load all of rm.sm[i] For whatever reason, Go insisted on loading rm.sm[i] in several chunks, even though it could be loaded in a single 64-bit block. Instead, let's reorder our loads to minimize the amount of memory we're uselessly moving around. This gives us about a 15% perf boost in github.com/julienschmidt/go-http-routing-benchmark's BenchmarkGoji_StaticAll, and questionable benefits (i.e., not distinguishable from noise but certainly no worse) on Goji's own benchmarks. --- web/fast_router.go | 2 +- web/router.go | 31 +++++++++++++++++-------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/web/fast_router.go b/web/fast_router.go index dea67db..b6f52b1 100644 --- a/web/fast_router.go +++ b/web/fast_router.go @@ -48,8 +48,8 @@ Unfortunately, the code implementing all of this is pretty bad (both inefficient and hard to read). Maybe someday I'll come and take a second pass at it. */ type state struct { - bs [3]byte mode smMode + bs [3]byte i int32 } type stateMachine []state diff --git a/web/router.go b/web/router.go index 8719e8c..137301c 100644 --- a/web/router.go +++ b/web/router.go @@ -170,29 +170,31 @@ func (rm routeMachine) route(c *C, w http.ResponseWriter, r *http.Request) (meth var i int for { - s := rm.sm[i] - if s.mode&smSetCursor != 0 { - p = r.URL.Path[s.i:] + sm := rm.sm[i].mode + if sm&smSetCursor != 0 { + si := rm.sm[i].i + p = r.URL.Path[si:] i++ continue } - length := int(s.mode & smLengthMask) + length := int(sm & smLengthMask) match := false if length <= len(p) { + bs := rm.sm[i].bs switch length { case 3: - if p[2] != s.bs[2] { + if p[2] != bs[2] { break } fallthrough case 2: - if p[1] != s.bs[1] { + if p[1] != bs[1] { break } fallthrough case 1: - if p[0] != s.bs[0] { + if p[0] != bs[0] { break } fallthrough @@ -202,20 +204,21 @@ func (rm routeMachine) route(c *C, w http.ResponseWriter, r *http.Request) (meth } } - if match && s.mode&smRoute != 0 { - if matchRoute(rm.routes[s.i], m, &methods, r, c) { - rm.routes[s.i].handler.ServeHTTPC(*c, w, r) + if match && sm&smRoute != 0 { + si := rm.sm[i].i + if matchRoute(rm.routes[si], m, &methods, r, c) { + rm.routes[si].handler.ServeHTTPC(*c, w, r) return 0, true } else { i++ } - } else if (match && s.mode&smJumpOnMatch != 0) || - (!match && s.mode&smJumpOnMatch == 0) { + } else if (match && sm&smJumpOnMatch != 0) || + (!match && sm&smJumpOnMatch == 0) { - if s.mode&smFail != 0 { + if sm&smFail != 0 { return methods, false } - i = int(s.i) + i = int(rm.sm[i].i) } else { i++ }