fasthttprouter
fasthttprouter copied to clipboard
Router allocates on the heap
Because the router is converting bytes slices to strings it allocates memory on the heap for each request.
This can be prevented by casting the slice to a string. ~The downside of this approach is that the UserValues will only be valid during the request as after the request they will change when the next request reuses the memory. It also means that changing the UserValue will change the request URI as well.~ This doesn't seem to be true.
diff --git a/router.go b/router.go
index 57c6e13..4e8fac9 100644
--- a/router.go
+++ b/router.go
@@ -75,6 +75,7 @@ package fasthttprouter
import (
"strings"
+ "unsafe"
"github.com/valyala/fasthttp"
)
@@ -293,8 +294,8 @@ func (r *Router) Handler(ctx *fasthttp.RequestCtx) {
defer r.recv(ctx)
}
- path := string(ctx.Path())
- method := string(ctx.Method())
+ path := b2s(ctx.Path())
+ method := b2s(ctx.Method())
if root := r.trees[method]; root != nil {
if f, tsr := root.getValue(path, ctx); f != nil {
f(ctx)
@@ -372,3 +373,12 @@ func (r *Router) Handler(ctx *fasthttp.RequestCtx) {
fasthttp.StatusNotFound)
}
}
+
+// b2s converts byte slice to a string without memory allocation.
+// See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ .
+//
+// Note it may break if string and/or slice header will change
+// in the future go versions.
+func b2s(b []byte) string {
+ return *(*string)(unsafe.Pointer(&b))
+}
Ooops, didn't see this issue but prepared a pull request: https://github.com/buaazp/fasthttprouter/pull/51
(in my tests and build with gcflags="-m -m" the method variable didn't escape)