突如其来的同步池分配
来源: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 收藏
-
477 收藏
-
486 收藏
-
439 收藏
-
357 收藏
-
352 收藏
-
101 收藏
-
440 收藏
-
212 收藏
-
143 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习