valyala / fasthttp

Fast HTTP package for Go. Tuned for high performance. Zero memory allocations in hot paths. Up to 10x faster than net/http
MIT License
21.91k stars 1.76k forks source link

RequestCtx.userValues's Reset method doesnot hep gc to recycle its items's key and value of userDataKV struct. #1812

Closed newacorn closed 3 months ago

newacorn commented 3 months ago

Test

func TestUserDataReset(t *testing.T) {
    ch := make(chan struct{}, 2)
    done := make(chan struct{}, 1)
    go func() {
        time.Sleep(time.Second * 1)
        c := Client{}
        req := AcquireRequest()
        req.SetRequestURI("http://localhost:8080")
        resp := AcquireResponse()
        err := c.Do(req, resp)
        if err != nil {
            t.Error(err)
            return
        }
        for i := 0; i < 5; i++ {
            time.Sleep(time.Millisecond * 10)
            runtime.GC()
        }
        select {
        case <-ch:
            done <- struct{}{}
        case <-time.NewTimer(time.Second * 1).C:
            t.Error("time out.")
            done <- struct{}{}
        }
    }()
    go func() {
        err := ListenAndServe(":8080", func(ctx *RequestCtx) {
            k := &key{}
            v := &value{}
            runtime.SetFinalizer(k, func(v *key) {
                ch <- struct{}{}
            })
            ctx.SetUserValue(k, v)
        })
        if err != nil {
            t.Error(err)
        }
    }()

    <-done
}

Test Result

=== RUN   TestUserDataReset
    userValues_prevent_garbage_after_reset_test.go:39: time out.
--- FAIL: TestUserDataReset (2.06s)

After a temp fix

func (d *userData) Reset() {
    args := *d
    n := len(args)
    for i := 0; i < n; i++ {
        v := args[i].value
        if vc, ok := v.(io.Closer); ok {
            vc.Close()
        }
        (*d)[i].value = nil  // fix code
        (*d)[i].key = nil // fix code
    }
    *d = (*d)[:0]
}

Test Again

=== RUN   TestUserDataReset
--- PASS: TestUserDataReset (1.06s)
PASS
erikdubbelboer commented 3 months ago

Good find, it's fixed in https://github.com/valyala/fasthttp/commit/0324e8d2a2831fa30478ced9202499d6cff14979