sync.Pool 对象重置问题
方式1: get -> operate-obj -> reset -> put
问题:get 的对象在操作时可能没有被reset 到
方式2: get -> reset -> operate-obj -> put
获取对象后,先 reset 在使用是没有问题的
gin 就是这样使用的
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { c := engine.pool.Get().(*Context) c.writermem.reset(w) c.Request = req c.reset() // 先reset engine.handleHTTPRequest(c) // 再使用 engine.pool.Put(c) // 使用之后直接 put }
cat test_syncpool.go
package test
import (
"strconv"
"sync"
"testing"
)
type A struct {
Name string
}
func (a *A) putValue(i int) {
a.Name = "A+" + strconv.Itoa(i)
}
func (a *A) reset() {
a.Name = ""
}
func Benchmark_A(b *testing.B) {
pool := &sync.Pool{
New: func() interface{} {
return new(A)
},
}
pool2 := &sync.Pool{
New: func() interface{} {
return new(A)
},
}
waitGroup := sync.WaitGroup{}
waitGroup.Add(1)
go func() {
defer waitGroup.Done()
for i := 0; i < b.N; i++ {
a := pool.Get().(*A)
//a.reset() // 方式2 没有问题
if a.Name != "" {
panic("name not empty")
}
a.putValue(i) // a.Name = "A+" + strconv.Itoa(i)
if a.Name == "" {
panic("name is empty")
}
a.reset() // 方式1 有问题的方式
pool.Put(a)
}
}()
waitGroup.Add(1)
go func() {
defer waitGroup.Done()
for i := 0; i < b.N; i++ {
a := pool.Get().(*A)
a.reset()
if a.Name != "" {
panic("name not empty")
}
a.putValue(i)
if a.Name == "" {
panic("name not empty")
}
pool.Put(a)
}
}()
waitGroup.Wait()
}
修改点
func (pool *taskPool) get() *Task {
task := pool.bp.Get().(*Task)
task.Reset()
return task
}
func (pool *taskPool) put(obj *Task) {
pool.bp.Put(obj)
}
执行用例 BenchmarkTimeWheel
➜ go-timewheel (master) ✗ go test -v -bench . -test.bench='TimeWheel$' -test.run ^$
goos: darwin
goarch: amd64
pkg: github.com/rfyiamcool/go-timewheel
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkAdd-12 1990670 1090 ns/op
BenchmarkTimeWheel/wheel-N-1m-12 1000000 1049 ns/op
BenchmarkTimeWheel/wheel-N-5m-12 1223064 1061 ns/op
BenchmarkTimeWheel/wheel-N-10m-12 1000000 1253 ns/op
PASS
ok github.com/rfyiamcool/go-timewheel 100.504s
问题点
task.callback 有值,但是 task.callback == nil 分支却执行了,断点在 task.callback() 时去执行 task.callback 确实是有值的
Task.stop = true
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 296245956@qq.com