Go 性能优化技巧 2/10

来源:互联网 发布:中华小说网源码 编辑:程序博客网 时间:2024/05/16 11:16

对于一些初学者,自知道 Go 里面的 array 以 pass-by-value 方式传递后,就莫名地引起 “恐慌”。外加诸多文章未作说明,就建议用 slice 代替 array,企图避免数据拷贝,提升性能。实际上,此做法有待商榷。某些时候怕会适得其反,倒造成不必要的性能损失。

用个简单的示例说明。

package mainimport (    "fmt")const capacity = 1024func array() [capacity]int {    var d [capacity]int    for i := 0; i < len(d); i++ {        d[i] = 1    }    return d}func slice() []int {    d := make([]int, capacity)    for i := 0; i < len(d); i++ {        d[i] = 1    }    return d}func main() {    fmt.Println(array())    fmt.Println(slice())}

代码很简单,两个函数分别返回 “内容相同” 的 array 和 slice。为避免编译器优化,特填充了全部数据,以模拟 “真实” 数据复制行为。接下来,看看性能测试对比。

package mainimport (    "testing")func BenchmarkArray(b *testing.B) {    for i := 0; i < b.N; i++ {        _ = array()    }}func BenchmarkSlice(b *testing.B) {    for i := 0; i < b.N; i++ {        _ = slice()    }}

这结果怕是颠覆了最初认知。array 非但拥有更好的性能,还避免了堆内存分配,也就是说减轻了 GC 压力。为什么会这样?

熟悉汇编的,怕是很容易看出来。函数 array 返回值的复制只需用 "CX + REP" 指令就可完成。

整个 array 函数完全在栈上完成,而 slice 函数则需执行 makeslice,继而在堆上分配内存,这就是问题所在。

对于一些短小的对象,复制成本远小于在堆上分配和回收操作。

Go Proverbs: A little copying is better than a little dependency.


最新动态,请扫码关注


1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信号被冻结了里面的钱怎么办 不懂公司产品却要接待老外怎么办 上菜时发现桌面摆不下新菜怎么办 超市买到过期产品商家不赔尝怎么办 皇帝成长计划2俘虏的士兵怎么办 晚上楼上有挪桌子的声音怎么办 金灶茶具出故障码e7怎么办 起亚k2灯泡掉进大灯总成怎么办 衣服上拆过线的针孔怎么办 驾考科目二坡道定点熄火怎么办 穿着超短裤感觉要漏屁股怎么办 台式电脑开机后无法进入系统怎么办 产后两年了肚子肥胖松弛怎么办 在作文中写上自己的名字怎么办 外出玩耍时迷路了你会怎么办 外出玩耍时孩子总喜欢乱跑怎么办? 如果真的物价高的受不了怎么办 每晚要5次真的受不了怎么办 五年级的学生钢笔字写不好怎么办 全麻醉药过后让人产生幻觉怎么办? 网贷小象优品上被别人冒用了怎么办 当你和老人产生冲突时该怎么办 百度网盘会员到期后容量怎么办 一个人不停的给你发视频聊天怎么办 被谋杀后的身后事应该怎么办 社保交了五年被单位辞退怎么办 桅子花叶子变黄叶杆蔫怎么办 薄荷养的都黄了干掉了怎么办 被烟草局没收的烟要是假烟怎么办 干了10年工程不想干了怎么办 在服务行业当服务员干不下去怎么办 高中生晚上偷着跑出去玩怎么办 货车高速忘记过安全检查站了怎么办 u盘上的文件名称乱码了怎么办 暖气管掉进去一点水泥渣怎么办 暗埋在瓷砖下的暖气管漏水怎么办 埋在瓷砖下面的水管漏水怎么办 埋在瓷砖下的水管漏水怎么办 水压太大把水管撑坏了怎么办 无效安装包与系统不兼容怎么办 圣空法师持五戒范戒了怎么办