Skip to content

Router allocates on the heap #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
erikdubbelboer opened this issue Jun 3, 2017 · 1 comment
Open

Router allocates on the heap #33

erikdubbelboer opened this issue Jun 3, 2017 · 1 comment

Comments

@erikdubbelboer
Copy link

erikdubbelboer commented Jun 3, 2017

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))
+}
@gallir
Copy link

gallir commented Apr 7, 2019

Ooops, didn't see this issue but prepared a pull request: #51

(in my tests and build with gcflags="-m -m" the method variable didn't escape)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants