Go 语言逃逸分析:内存管理的关键

2024-05-24 23:44

本文主要是介绍Go 语言逃逸分析:内存管理的关键,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 1 逃逸分析是什么?
  • 2 逃逸分析的基本思想是什么?
  • 3 逃逸分析的分配原则是什么?
  • 4 如何进行逃逸分析?
  • 5 逃逸分析案例
    • 5.1 变量在函数外存在引用
    • 5.2 引用类型的逃逸
    • 5.3 闭包捕获变量
    • 5.4 变量占用内存较大
  • 6 变量会逃逸到堆上的原因有哪些?
  • 7 如何避免逃逸?
  • 8 逃逸分析的作用有哪些?
  • 9 学习交流

前言

在正式学习逃逸分析时,我们需要提前补充变量的声明周期的概念。


  • 栈(stack):在GO语言中,栈是调用栈(call stack) 的简称。在GO程序运行时,每一个Goroutine单独维护一个自己的栈区仅允许自己使用不能被其他Goroutine使用。一个栈通常包含许多栈帧(stack frame),它描述的是函数之间的调用关系。栈的内存是由编译器自动进行分配释放的。栈区主要存储函数参数局部变量调用函数帧,它们随函数的创建而分配随函数的退出而销毁
  • 堆(heap):与栈(stack)不同的是,堆区的内存是由编译器工程师共同负责管理分配,交给Runtime GC释放。在堆上分配内存时,必须找到一块足够大的内存来存放新的变量数据。在堆上释放内存时,垃圾回收器会扫描内存空间中不被使用的对象并释放其内存。在我们开发过程中,其实考虑内存管理,主要是考虑堆内存的管理。

变量的声明周期与变量作用域的关系

  • 全局变量:它的生命周期与程序的生命周期一致
  • 局部变量:它的生命周期是动态的,从变量创建开始,到变量不再使用结束。
  • 形参和函数的返回值:它们都是属于局部变量,在函数被调用时创建,调用结束时被销毁。

1 逃逸分析是什么?

逃逸分析(Escape Analysis)是一种重要的编译时优化技术,决定将变量分配到 堆(heap)上 还是 栈(stack)上
通过逃逸分析,编译器可以判断变量的生命周期作用范围,从而选择最合适的内存分配方式,以提高程序的性能和减少内存开销


2 逃逸分析的基本思想是什么?

[!warning]- 思考: 如何知道GO变量的生命周期是完全可知的?

  • 判断变量是值类型还是引用类型,值类型是确定的完全可知的,引用类型是不可知的,不知道是否该变量被其他函数使用。
  • 检查变量的生命周期是否是完全可知的,如果是,则在栈上分配内存。
  • 如何检查不是完全可知的,也就是我们说的逃逸,必须在堆上分配内存。

3 逃逸分析的分配原则是什么?

[!warning]- 如何确定参数类型是不确定的?

  • 变量的数据类型采用interface{},编译期无法确定其具体的参数类型,所以分配到堆中。
  • 什么样的数据类型是确定的? 比如:声明了一个确定数据类型int的变量`var num int
  • GO的逃逸分析是在编译期间完成的,编译期间无法确定的参数类型是放在堆中的。
  • 变量在函数外存在引用,则必定放在
  • 变量占用内存较大,则优先放在
  • 变量在函数外部没有引用,则优先放在中。

4 如何进行逃逸分析?

逃逸分析我们可以通过命令查看结果,-gcflags选项用于向 Go 编译器传递编译标志。这些标志可以用来启用或禁用特定的编译器功能,包括逃逸分析

  • 查看基本的逃逸分析和内联信息,适用于一般情况
go build -gcflags="-m" main.go

[!warning]+ 命令解释说明

  • -m:表示输出有关内联(inlining)逃逸分析的信息

  • 查看更详细的优化信息和逃逸分析结果,并禁用内联优化,适用于需要深入调试和分析的情况。
go build -gcflags '-m -m -l'  main.go

[!warning]+ 命令解释说明

  • -m -m:表示多次使用 -m 标志,增加详细程度,会输出更多的优化信息,包括逃逸分析和内联优化的详细信息。
  • -l:表示禁用内联优化。

5 逃逸分析案例

5.1 变量在函数外存在引用

package mainimport "fmt"func createPointer() *int {var x intreturn &x  // x 逃逸到堆上
}func main() {p := createPointer()fmt.Println(*p)
}

[!note]+ 代码解析说明

  • 函数 createPointer 返回了局部变量 x 的地址,这意味着 x 在函数返回后仍然需要存在。
  • 因此,编译器将 x 分配到堆上,并在逃逸分析的输出中提示 &x escapes to heap

5.2 引用类型的逃逸

  • 例如:切片、映射、接口等引用类型的变量,如果它们的底层数据逃逸,则这些变量也会逃逸。
func createSlice() []int {s := make([]int, 10) return s // s 逃逸到堆上 
}

5.3 闭包捕获变量

如果闭包捕获了外部变量,该变量会逃逸到堆上。

func createClosure() func() { var x int return func() { x++ // x 逃逸到堆上 }
}

5.4 变量占用内存较大

func createManySlice() []int {  var s []int  for i := 0; i < 1000; i++ {  s = make([]int, 10)  }  return s // s 逃逸到堆上  
}

6 变量会逃逸到堆上的原因有哪些?

  • 函数返回值:如果返回一个局部变量的指针或引用,该变量会逃逸到堆上。
  • 闭包捕获:如果闭包捕获了外部变量,该变量会逃逸到堆上。
  1. 长生命周期:如果变量的生命周期超出了其作用域,如通过指针或引用传递给其他函数或存储在全局变量中。

7 如何避免逃逸?

避免逃逸,也就是说减少不必要的堆分配。

  • 避免返回局部变量的指针或引用
  • 尽量减少闭包捕获的外部变量
  • 使用值传递而不是指针传递

8 逃逸分析的作用有哪些?

  • 提升内存分配效率:栈上分配比在堆上分配效率更高效,栈上的内存可以自动回收,而堆上的内存需要垃圾回收器管理。
  • 减少垃圾回收开销:减少不必要的堆分配,可以降低垃圾回收的频率和开销。
  • 提高程序性能:优化内存分配,提升程序运行效率。

9 学习交流

为了方便大家一起学习一起进步,我创建了一个学习交流的平台
感兴趣的朋友们可以加我微信:LH913582934,备注:CSDN。

这篇关于Go 语言逃逸分析:内存管理的关键的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/999873

相关文章

C语言中联合体union的使用

本文编辑整理自: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=179471 一、前言 “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

用Microsoft.Extensions.Hosting 管理WPF项目.

首先引入必要的包: <ItemGroup><PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /><PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /><PackageReference Include="Serilog

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

关于如何更好管理好数据库的一点思考

本文尝试从数据库设计理论、ER图简介、性能优化、避免过度设计及权限管理方面进行思考阐述。 一、数据库范式 以下通过详细的示例说明数据库范式的概念,将逐步规范化一个例子,逐级说明每个范式的要求和变换过程。 示例:学生课程登记系统 初始表格如下: 学生ID学生姓名课程ID课程名称教师教师办公室1张三101数学王老师101室2李四102英语李老师102室3王五101数学王老师101室4赵六103物理陈

springboot家政服务管理平台 LW +PPT+源码+讲解

3系统的可行性研究及需求分析 3.1可行性研究 3.1.1技术可行性分析 经过大学四年的学习,已经掌握了JAVA、Mysql数据库等方面的编程技巧和方法,对于这些技术该有的软硬件配置也是齐全的,能够满足开发的需要。 本家政服务管理平台采用的是Mysql作为数据库,可以绝对地保证用户数据的安全;可以与Mysql数据库进行无缝连接。 所以,家政服务管理平台在技术上是可以实施的。 3.1

人工和AI大语言模型成本对比 ai语音模型

这里既有AI,又有生活大道理,无数渺小的思考填满了一生。 上一专题搭建了一套GMM-HMM系统,来识别连续0123456789的英文语音。 但若不是仅针对数字,而是所有普通词汇,可能达到十几万个词,解码过程将非常复杂,识别结果组合太多,识别结果不会理想。因此只有声学模型是完全不够的,需要引入语言模型来约束识别结果。让“今天天气很好”的概率高于“今天天汽很好”的概率,得到声学模型概率高,又符合表达

C语言 将“China”译成密码

将“China”译成密码,密码规律是:用原来的字母后面的第4个字母代替原来的字母。例如,字母“A”后面的第4个字母是“E”,用“E”代替“A”。因此,“China”应译为“Glmre”。编译程序用付赋初值的方法使c1,c2,c3,c4,c5这五个变量的值分别为“C”,“h”,“i”,“n”,“a”,经过运算,使c1,c2,c3,c4,c5分别变成“G”,“l”,“m”,“r”,“e”。分别用put