突如其来的同步池分配
来源:stackoverflow
时间:2024-03-01 13:15:25 416浏览 收藏
编程并不是一个机械性的工作,而是需要有思考,有创新的工作,语法是固定的,但解决问题的思路则是依靠人的思维,这就需要我们坚持学习和更新自己的知识。今天golang学习网就整理分享《突如其来的同步池分配》,文章讲解的知识点主要包括,如果你对Golang方面的知识点感兴趣,就不要错过golang学习网,在这可以对大家的知识积累有所帮助,助力开发能力的提升。
all,学习golang一个月了,遇到了这个问题。基本上我正在尝试重用sync.pool中的[]字节来进行一些哈希处理。
我添加了一个最小可行的示例来重现它:
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 不会为 []byte 分配新内存,但我在这里看到 m.pool.get() 进行了额外的分配。
benchmark_writespan-12 30000000 47.6 ns/op 32 b/op 1 分配/操作 经过
这背后的解释是什么?我还在这里尝试了一些更简单的基准测试:
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)
}
但这显示没有分配:
benchmark_2-12 2000000000 0.00 ns/op 0 b/op 0 分配/操作
感谢这里的任何帮助! (如果这不是sync.pool的使用方式,有什么建议吗?)
已编辑:
好的,我在 writespan 基准测试中添加了一个简单的循环,现在它给出了以下基准测试:
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/操作 160 b/操作 5 分配/操作
看起来池在每次写入时分配 32b,难道它不应该在第一次获取后重用相同的 byte[] 吗?
更新 @jimb我确实在实际代码中有一些逻辑可以更新字节切片和哈希值。像下面这样:
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)
我不确定这是否算作作为短期对象的一部分维护的空闲列表,您能否更具体地说明这一点?
解决方案
我想我找到了背后的原因。在我的真实代码中,我曾经有:
bytepool: &sync.pool{
new: func() interface{} {
return make([]byte, length)
},
},
...
...
bytepool.get().([]byte)
不知何故,当我将其更改为
bytepool: &sync.Pool{
New: func() interface{} {
byteP := make([]byte, length)
return &byteP
},
},
...
...
bytepool.Get().(*[]byte)
分配下降到 0。很抱歉,大家看起来不是sync.pool 的问题,而是底层数据结构的问题。不过还是感谢您的评论!
以上就是《突如其来的同步池分配》的详细内容,更多关于的资料请关注golang学习网公众号!
-
502 收藏
-
502 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
139 收藏
-
204 收藏
-
325 收藏
-
478 收藏
-
486 收藏
-
439 收藏
-
357 收藏
-
352 收藏
-
101 收藏
-
440 收藏
-
212 收藏
-
143 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习