Golang——逃逸分析

embedded/2024/9/23 4:42:51/

逃逸分析是指由编译器决定内存分配到堆上还是栈上。当我们在函数中申请了一个新的对象:

  • 如果分配到栈中,则函数执行结束后可自动将内存回收。
  • 如果分配到堆中,则函数执行结束后,不会自动将内存释放掉,需要GC在进行清除。

逃逸分析使Go语言能够将局部变量返回,程序员不需要担心局部变量分配到栈上还是堆上。并且Go程序员不需要像C程序员一样,担心内存泄漏的问题。

逃逸策略:

在函数中申请一个新的对象时,编译器会根据该对象是否被函数外部引用来确定是否逃逸。

  • 如果变量在函数外部没有引用,则优先放到栈上。
  • 如果变量在函数外部存在引用,则必定放到堆上。

注意,对于一个仅在函数内部使用的变量,也有可能放到堆上,比如内存过大超过栈的存储能力。我们很难通过肉眼直接判断函数内部的变量是否发生了逃逸,我们需要借助go build -gcflags=-m指令判断是否发生逃逸分析。

逃逸场景:

1.函数返回指针,会发生指针逃逸。如果我们的返回的结构体中包含指针,也会发生逃逸,比如slice、 map。

func main() {getNum()
}
func getNum() *int {i := 1return &i
}# ExpertProgramming/chapter04/escape/move_to_heap
./main.go:6:6: can inline getNum
./main.go:3:6: can inline main
./main.go:4:8: inlining call to getNum
./main.go:7:2: moved to heap: i

2.栈空间不足以存放当前创建的对象时,会将新创建的对象分配到堆上,发生逃逸。

func main() {s := make([]int, 1000000, 1000001)for index, value := range s {fmt.Println(index, value)}
}./main.go:10:14: inlining call to fmt.Println
./main.go:8:11: make([]int, 1000000, 1000001) escapes to heap
./main.go:10:14: ... argument does not escape
./main.go:10:15: index escapes to heap
./main.go:10:22: value escapes to heap

3.在编译期间很难确定其对象的具体类型时,会发生逃逸。比如参数为interface类型的函数

func main() {s := "wang"fmt.Println(s)
}./main.go:9:13: inlining call to fmt.Println
./main.go:9:13: ... argument does not escape
./main.go:9:14: s escapes to heap

4.闭包的引用对象

func main() {num := Fibonacci()for i := 0; i < 10; i++ {fmt.Println(num())}
}func Fibonacci() func() int {a, b := 0, 1return func() int {a, b = b, a+breturn a}
}./main.go:10:14: ... argument does not escape
./main.go:10:18: ~R0 escapes to heap
./main.go:15:2: moved to heap: a
./main.go:15:5: moved to heap: b
./main.go:16:9: func literal escapes to heap

5.切片长度不确定的时候也会发生逃逸,即使这时候我们不返回切片

func main() {getSlice()
}func getSlice() {length := 3s1 := make([]int, length)s1[0] = 9
}./main.go:7:6: can inline getSlice
./main.go:3:6: can inline main
./main.go:4:10: inlining call to getSlice
./main.go:4:10: make([]int, length) escapes to heap
./main.go:9:12: make([]int, length) escapes to heap

总结:

逃逸分析的目的是为了确定对象分配到了堆上还是分配到了栈上。有了逃逸分析,我们可以非常方便地返回函数里面的变量,这方便了我们的开发,但也有可能会造成我们程序的性能下降。因为分配到堆上的变量,需要GC进行回收。而GC运行的时候,会发生STW。所以,我们要减少不合理的逃逸现象,减轻GC的负担。


http://www.ppmy.cn/embedded/92849.html

相关文章

PHP简单零售收银台系统源码小程序

&#x1f6d2;轻松上手&#xff01;简单零售收银台系统&#xff0c;让经营更省心&#x1f4b8; &#x1f680; 开篇&#xff1a;告别繁琐&#xff0c;拥抱高效收银新时代 嘿&#xff0c;小店主们&#xff01;&#x1f44b; 还在为每天繁琐的收银工作头疼吗&#xff1f;是时候…

贵阳高新区:加强数字人才培育 引领数字经济未来

在近期举行的贵阳高新区&#xff08;贵州科学城&#xff09;2024年科技创新与成果交流夏季活动中&#xff0c;来自清华大学2022级大数据&#xff08;贵州&#xff09;全日制工程硕士专业的学生们展示了他们在城市公交数据挖掘、通勤线路优化、场景数据的稳定训练以及营运车辆风…

如何在Java、C、Ruby语言中使用Newscatcher API

Newscatcher 世界实时新闻聚合API 一款强大的数据服务工具&#xff0c;它通过先进的网络爬虫技术&#xff0c;实时从全球超过70,000个新闻源聚合新闻内容。这个API能够提供全面、多角度的新闻报道&#xff0c;包括但不限于标题、作者、发布日期、全文内容以及媒体资源链接。它使…

centos 安装nacos

nacos官网下载安装包&#xff08;安装nacos之前&#xff0c;先下载安装好jdk&#xff09; 概览 | Nacos 官网 2.下载好nacos压缩包之后&#xff0c;上传到linux目录中&#xff08;在/opt/目录下建好一个文件夹&#xff09; 将nacos解压 uzip nacos-server-1.4.7.zip 进入naco…

GoLang 安装

golang学习笔记 goland 安装 To use Go programming language in Visual Studio Code (VSCode), you can follow these steps: 1. Install Go: Download and install the latest version of Go from the official Go website (https://golang.org/dl/). 2. Install VSCode:…

av.codec.codec.UnknownCodecError: libx264

遇到 av.codec.codec.UnknownCodecError: libx264 这个错误通常意味着 PyAV 库尝试使用 libx264 编码器来编码或解码视频&#xff0c;但该编码器在你的系统中不可用。 libx264 是一个广泛使用的 H.264 视频编码库。如果你正在使用 PyAV 来处理视频&#xff0c;特别是当你尝试读…

《Redis设计与实现》读书笔记-复制

目录 1.概述 2.复制命令 3.部分重同步过程 4.部分重同步实现 4.1复制偏移量 4.2复制积压缓冲区 4.3服务器运行ID 5.总结 1.概述 在redis 通过向从服务器发送命令&#xff1a;SLAVE OF&#xff0c;让从服务器复制主服务器&#xff0c;成为复制。 复制的目的 让从服务器…

php怎么解决高并发的问题

处理PHP应用中的高并发问题是一个复杂的挑战&#xff0c;它通常涉及到多个层面的优化和策略。以下是一些常见的方法和策略&#xff0c;可以帮助你解决或缓解PHP应用中的高并发问题&#xff1a; 优化代码和数据库&#xff1a; - 代码优化&#xff1a;确保PHP代码尽可能高效&a…