文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Go 语言内存逃逸案例

2024-12-01 18:22

关注

Go 语言编译器可以通过逃逸分析决定内存分配到栈空间或堆空间。但是,分配到栈空间的对象在某些情况中会逃逸到堆空间。我们可以使用 Go 工具链查看对象是否发生内存逃逸。

为了提升 Go 应用程序的性能,我们应该避免 Go 应用程序中出现内存逃逸的现象,本文我们介绍 Go 语言内存逃逸的几种典型案例。

02 内存逃逸案例

指针逃逸

示例代码:

func main() {
pointerEscape(1, 2)
}

// pointerEscape 指针逃逸
func pointerEscape(a, b int) *int {
sum := a + b
return &sum
}

输出结果:

go build --gcflags '-m -m -l' main.go
# command-line-arguments
./main.go:9:2: sum escapes to heap:
./main.go:9:2: flow: ~r0 = &sum:
./main.go:9:2: from &sum (address-of) at ./main.go:10:9
./main.go:9:2: from return &sum (return) at ./main.go:10:2
./main.go:9:2: moved to heap: sum

阅读上面这段代码,我们创建一个函数 pointerEscape​,函数内部创建一个局部变量 sum,返回结果是该变量的指针。

通过执行 go build --gcflags '-m -m -l' main.go 的输出结果,我们发现函数中定义的局部变量 sum 逃逸到堆空间,这就是所谓的指针逃逸。

函数 pointerEscape​ 的局部变量 sum​ 本来应该在函数结束时被回收,但是在 main 函数中会继续使用 sum​ 变量的内存地址,导致变量 sum 被逃逸到堆上。

如果想要避免示例函数的返回结果出现内存逃逸,可以使用值类型的返回结果,这样就带来另外一个问题。

如果返回结果是一个比较大的变量,比如返回结果是较大的结构体类型的变量,我们使用值类型将会造成比较大的内存占用。

所以,我们在实际项目开发中,需要根据实际情况,合理使用返回结果的类型。

动态类型逃逸

示例代码:

func main() {
fmt.Println("hello world")
}

输出结果:

go run -gcflags '-m -m -l' main.go
# command-line-arguments
./main.go:6:14: "hello world" escapes to heap:
./main.go:6:14: flow: {storage for ... argument} = &{storage for "hello world"}:
./main.go:6:14: from "hello world" (spill) at ./main.go:6:14
./main.go:6:14: from ... argument (slice-literal-element) at ./main.go:6:13
./main.go:6:14: flow: {heap} = {storage for ... argument}:
./main.go:6:14: from ... argument (spill) at ./main.go:6:13
./main.go:6:14: from fmt.Println(... argument...) (call parameter) at ./main.go:6:13
./main.go:6:13: ... argument does not escape
./main.go:6:14: "hello world" escapes to heap

阅读上面这段代码,我们在 main 函数中,使用 fmt.Println()​ 打印字符串 hello world。

通过执行 go run -gcflags '-m -m -l' main.go​ 的输出结果,我们发现使用 fmt.Println()​ 打印的字符串 hello world 逃逸到堆上,这就是所谓的动态类型逃逸。

因为 fmt.Println() 接收的参数是空接口类型,Go 编译器无法确定入参变量的具体类型,所以此类情况变量也会逃逸到堆上。

03 总结

本文我们介绍两个典型的内存逃逸的案例,除此之外,以下几种情况,也会发生内存逃逸。

感兴趣的读者朋友们,可以自行编写上述几种情况的示例代码,验证是否会发生内存逃逸。

来源:Golang语言开发栈内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯