首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >意外sync.Pool分配

意外sync.Pool分配
EN

Stack Overflow用户
提问于 2019-02-22 17:03:29
回答 1查看 955关注 0票数 2

大家都已经学了一个月了,遇到了这个问题。基本上,我试图重用sync.Pool中的一个[]字节来执行散列操作。

我为复制它添加了一个最小可行的示例如下:

代码语言:javascript
复制
type mWriter struct {
    pool *sync.Pool
}

func (m *mWriter) writeSpan(span interface{}) {
    haha := m.pool.Get().([]byte)
    // in real code some actions here instead of simply setting haha[0] = 1
    haha[0] = 1
    m.pool.Put(haha)
}

func NewWriter() *mWriter {
    bytepool := &sync.Pool{
        New: func() interface{} {
            return make([]byte, 16)
        },
    }
    return &mWriter{
        pool: bytepool,
    }
}

func Benchmark_WriteSpan(b *testing.B) {
    c := NewWriter()

    b.ResetTimer()
    b.ReportAllocs()
    for it := 0; it < b.N; it++ {
        c.writeSpan(nil)
    }
}

在我的印象中,sync.Pool没有为[]字节分配新内存,但是我在这里看到了m.pool.get()的额外分配。

Benchmark_WriteSpan-12 30000000 47.6ns/op 32 B/op 1分配程序/op PASS

这背后的解释是什么?我还在这里尝试了一些更简单的基准测试:

代码语言:javascript
复制
func Benchmark_2(b *testing.B) {
    // Initializing pool
    pool := &sync.Pool{
        New: func() interface{} {
            return make([]byte, 4)
        },
    }
    b.ResetTimer()
    b.ReportAllocs()
    // Get hold of instance one
    one := pool.Get().([]byte)
    one[1] = 1
    one[2] = 2
    // Submit back the instance after using
    pool.Put(one)
}

但这表明没有分配:

基准2-12 2000000000 0.00 ns/op 0 B/op 0配体/op

感谢你们的帮助!(如果sync.Pool不是这样使用的,那么有什么建议吗?)

编辑:

好的,我在基准测试中添加了一个简单的循环到writeSpan中,现在它给出了以下基准:

代码语言:javascript
复制
func Benchmark_WriteSpan(b *testing.B) {
    c := NewWriter()

    b.ResetTimer()
    b.ReportAllocs()
    for it := 0; it < b.N; it++ {
        for i := 0; i < 5; i++ {
            c.writeSpan(nil)
        }
    }
}

Benchmark_WriteSpan-12 5000000 226 ns/op 160 B/op 5配体/op

看起来这个池在每次写入时分配32B,是不是应该在第一次获得之后重用相同的byte[]呢?

Update @JimB我在实际代码中确实有一些逻辑,用于更新字节片和散列。如下所示:

代码语言:javascript
复制
    byteSlice := ds.poolInstance.bytepool.Get().([]byte)
    copy(byteSlice[:len(ds.hashSalt)], ds.hashSalt)
    span.TraceID.MarshalTo(byteSlice[len(ds.hashSalt):])
    hashVal := ds.hashBytes(byteSlice) 
    ds.poolInstance.bytepool.Put(byteSlice)

我不确定这是否算为作为短期对象的一部分而维护的空闲列表,您能对此做更具体的说明吗?

EN

回答 1

Stack Overflow用户

发布于 2019-02-22 19:58:37

我想我找到了原因。在我的真实代码中,我曾经有:

代码语言:javascript
复制
bytepool: &sync.Pool{
    New: func() interface{} {
        return make([]byte, length)
    },
},
...
...
bytepool.Get().([]byte)

不知怎么的当我把它改成

代码语言:javascript
复制
bytepool: &sync.Pool{
    New: func() interface{} {
        byteP := make([]byte, length)
        return &byteP
    },
},
...
...
bytepool.Get().(*[]byte)

分配下降到0。很抱歉,人们看起来不是sync.Pool的问题,而是底层数据结构的问题。不过,谢谢你的评论!

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54831932

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档