一文搞懂Golang中的内存逃逸

 更新时间:2022年09月08日 14:08:40   作者:1个俗人  
我们都知道go语言中内存管理工作都是由Go在底层完成的,这样我们可以不用过多的关注底层的内存问题。本文主要总结一下 Golang内存逃逸分析,需要的朋友可以参考以下内容,希望对大家有帮助

前言

我们都知道go语言中内存管理工作都是由Go在底层完成的,这样我们可以不用过多的关注底层的内存问题,有更多的精力去关注业务逻辑, 但掌握内存的管理,理解内存分配机制,可以让你写出更高效的代码,本文主要总结一下 Golang内存逃逸分析,需要的朋友可以参考以下内容,希望对大家有帮助。

什么是内存逃逸

在了解什么是内存逃逸之前,我们先来了解两个概念,栈内存和堆内存。

堆内存(Heap):一般来讲是人为手动进行管理,手动申请、分配、释放。一般硬件内存有多大堆内存就有多大。适合不可预知大小的内存分配,分配速度较慢,而且会形成内存碎片。

栈内存(Stack):是一种拥有特殊规则的线性表数据结构。由编译器进行管理,自动申请、分配、释放。大小一般是固定的。

通过上面我们可以看出堆分配昂贵,栈分配廉价,在go中所有内存优先栈分配,那么,Go 编译器怎么知道某个变量需要分配在栈上,还是堆上呢?

逃逸分析是用于堆和栈分配进行选择,通过在编译时期做gc,编译器追踪变量在代码块的作用域,判断变量在整个运行周期是否在运行时完全可知,通过校验可以在栈上分配;否则逃逸到堆上;逃逸分析由编译器完成,作用于编译阶段。

查看对象是否发生逃逸

Go 语言工具链提供了查看对象是否逃逸的方法,我们在执行 go build 时,配合使用参数 -gcflags 开启编译器支持的额外功能,例如:

go build -gcflags '-m -l' main.go

-m 会打印出逃逸分析的优化策略,实际上最多总共可以用 4 个 -m,但是信息量较大,一般用 1 个就可以了

-l 会禁用函数内联,在这里禁用掉 inline 能更好的观察逃逸情况,减少干扰。

除了使用编译参数之外,我们还可以使用一种更底层的,更硬核,也更准确的方式来判断一个对象是否逃逸,那就是: 通过反编译命令查看

go tool compile -S main.go

示例:

func main()  {
	sum(1, 2)
}
func sum(a, b int) *int {
	res := a + b
	return &res
}

结果如下,第7行变量 res 逃逸到了堆上

内存逃逸分析的意义

通过逃逸分析,可以尽量把那些不需要分配到堆上的变量直接分配到栈上,堆上的变量少了,会减轻分配堆内存的开销,同时也会减少GC的压力,提高程序的运行速度。

怎么避免内存逃逸

尽量减少外部指针引用,必要的时候可以使用值传递;

对于自己定义的数据大小,有一个基本的预判,尽量不要出现栈空间溢出的情况;

Golang中的接口类型的方法调用是动态调度,如果对于性能要求比较高且访问频次比较高的函数调用,应该尽量避免使用接口类型;

尽量不要写闭包函数,可读性差且发生逃逸。

小结

本文主要介绍了 Go 语言逃逸分析,它可以帮助我们合理分配对象的内存空间。

我们知道分配到堆内存空间的对象,会导致 Go 执行垃圾回收,而垃圾回收会占用系统资源,降低应用程序本身可使用的系统资源。

所以,我们在实际项目开发中,可以借助 Go 工具链分析对象是否会发生逃逸,尽量避免一些不必要的对象逃逸。

到此这篇关于一文搞懂Golang中的内存逃逸的文章就介绍到这了,更多相关Go内存逃逸内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go使用支付宝沙箱实现支付宝支付的操作步骤

    go使用支付宝沙箱实现支付宝支付的操作步骤

    支付宝沙箱支付是支付宝提供的一个测试环境,用于开发者在不影响真实交易的情况下进行支付接口的开发和调试,本文给大家介绍了go使用支付宝沙箱实现支付宝支付的操作步骤,文中有详细的代码示例和图文供大家参考,需要的朋友可以参考下
    2024-03-03
  • Go中strings包的基本使用示例代码

    Go中strings包的基本使用示例代码

    本文详细介绍了Go语言中strings包的基本使用方法,包括字符串的前缀、后缀判断,字符串包含、索引查找、字符串替换、计数、重复、大小写转换、修剪、分割、拼接以及数据类型转换等功能,示例代码丰富,适合初学者和需要使用字符串处理功能的开发者参考学习
    2024-10-10
  • Go语言WaitGroup使用时需要注意的坑

    Go语言WaitGroup使用时需要注意的坑

    Go语言中WaitGroup的用途是它能够一直等到所有的goroutine执行完成,并且阻塞主线程的执行,直到所有的goroutine执行完成。之前一直使用也没有问题,但最近通过同事的一段代码引起了关于WaitGroup的注意,下面这篇文章就介绍了WaitGroup使用时需要注意的坑及填坑。
    2016-12-12
  • Golang Type关键字的使用

    Golang Type关键字的使用

    Type关键字在Go语言中作用很重要,比如定义结构体,接口,还可以自定义类型,定义类型别名等,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • Go语言底层原理互斥锁的实现原理

    Go语言底层原理互斥锁的实现原理

    这篇文章主要介绍了Go语言底层原理互斥锁的实现原理,Go sync包提供了两种锁类型,分别是互斥锁sync.Mutex和读写互斥锁sync.RWMutex,都属于悲观锁,更多相关内容需要的朋友可以查看下面文章内容
    2022-08-08
  • Go语言:打造优雅数据库单元测试的实战指南

    Go语言:打造优雅数据库单元测试的实战指南

    Go语言数据库单元测试入门:聚焦高效、可靠的数据库代码验证!想要确保您的Go应用数据层坚如磐石吗?本指南将手把手教您如何利用Go进行数据库单元测试,轻松揪出隐藏的bug,打造无懈可击的数据处理逻辑,一起来探索吧!
    2024-01-01
  • 深度解析Go语言中的未使用导入和变量

    深度解析Go语言中的未使用导入和变量

    本文解析Go语言中未使用导入和变量的处理机制,强调其强制使用规则对代码质量的保障,通过移除冗余、使用空白标识符及工具清理,可提升代码可读性与性能
    2025-06-06
  • Golang中unicode码和中文的互相转换函数使用

    Golang中unicode码和中文的互相转换函数使用

    这篇文章主要为大家介绍了Golang中unicode码和中文的互相转换函数使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 深入解析Go 变量字符串与字符编码问题

    深入解析Go 变量字符串与字符编码问题

    Go的字符串是由单个字节连接起来的,Go语言的字符串的字节使用UTF-8编码标识Unicode文本,接下来通过本文给大家介绍下Go变量字符串与字符编码问题,需要的朋友可以参考下
    2022-04-04
  • go操作Kafka使用示例详解

    go操作Kafka使用示例详解

    这篇文章主要为大家介绍了go操作Kafka使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12

最新评论