面试官:谈谈 Go 内存逃逸机制

news2024/9/23 8:16:20

大家好,我是木川

一、概念

在一段程序中,每一个函数都会有自己的内存区域存放自己的局部变量、返回地址等,这些内存会由编译器在栈中进行分配,每一个函数都会分配一个栈桢,在函数运行结束后进行销毁,但是有些变量我们想在函数运行结束后仍然使用它,那么就需要把这个变量在堆上分配,这种从"栈"上逃逸到"堆"上的现象就成为内存逃逸。

在栈上分配的地址,一般由系统申请和释放,不会有额外性能的开销,比如函数的入参、局部变量、返回值等。在堆上分配的内存,如果要回收掉,需要进行 GC,那么GC 一定会带来额外的性能开销。编程语言不断优化GC算法,主要目的都是为了减少 GC带来的额外性能开销,变量一旦逃逸会导致性能开销变大。

二、逃逸机制

编译器会根据变量是否被外部引用来决定是否逃逸:

  1. 如果函数外部没有引用,则优先放到栈中;

  2. 如果函数外部存在引用,则必定放到堆中;

  3. 如果栈上放不下,则必定放到堆上;

逃逸分析也就是由编译器决定哪些变量放在栈,哪些放在堆中,通过编译参数-gcflag=-m可以查看编译过程中的逃逸分析,发生逃逸的几种场景如下:

指针逃逸

package main

func escape1() *int {
 var a int = 1
 return &a
}

func main() {
 escape1()
}

通过go build -gcflags=-m main.go查看逃逸情况:

./main.go:4:6: moved to heap: a

函数返回值为局部变量的指针,函数虽然退出了,但是因为指针的存在,指向的内存不能随着函数结束而回收,因此只能分配在堆上。

栈空间不足

package main

func escape2() {
 s := make([]int, 0, 10000)
 for index, _ := range s {
  s[index] = index
 }
}

func main() {
 escape2()
}

通过go build -gcflags=-m main.go查看逃逸情况:

./main.go:4:11: make([]int, 10000, 10000) escapes to heap

当栈空间足够时,不会发生逃逸,但是当变量过大时,已经完全超过栈空间的大小时,将会发生逃逸到堆上分配内存。局部变量s占用内存过大,编译器会将其分配到堆上

变量大小不确定

package main

func escape3() {
 number := 10
 s := make([]int, number) // 编译期间无法确定slice的长度
 for i := 0; i < len(s); i++ {
  s[i] = i
 }
}

func main() {
 escape3()
}

编译期间无法确定slice的长度,这种情况为了保证内存的安全,编译器也会触发逃逸,在堆上进行分配内存。直接s := make([]int, 10)不会发生逃逸

动态类型

动态类型就是编译期间不确定参数的类型、参数的长度也不确定的情况下就会发生逃逸

空接口 interface{} 可以表示任意的类型,如果函数参数为 interface{},编译期间很难确定其参数的具体类型,也会发生逃逸。

package main

import "fmt"

func escape4() {
 fmt.Println(1111)
}

func main() {
 escape4()
}

通过go build -gcflags=-m main.go查看逃逸情况:

./main.go:6:14: 1111 escapes to heap

fmt.Println(a ...interface{})函数参数为interface,编译器不确定参数的类型,会将变量分配到堆上

闭包引用对象

package main

func escape5() func() int {
 var i int = 1
 return func() int {
  i++
  return i
 }
}

func main() {
 escape5()
}

通过go build -gcflags=-m main.go查看逃逸情况:

./main.go:4:6: moved to heap: i

闭包函数中局部变量 i 在后续函数是继续使用的,编译器将其分配到堆上

三、总结

  1. 栈上分配内存比在堆中分配内存效率更高

  2. 栈上分配的内存不需要 GC 处理,而堆需要

  3. 逃逸分析目的是决定内分配地址是栈还是堆

  4. 逃逸分析在编译阶段完成

  5. 只要是指针变量都会在堆上分配,所以对于小变量我们还是使用传值(而不是传指针),效率更高一点

最后给自己的原创 Go 面试小册打个广告,如果你从事 Go 相关开发,欢迎扫码购买,目前 10 元买断,加下面的微信发送支付截图额外赠送一份自己录制的 Go 面试题讲解视频

fe838949b02bf0d04169b23fe89c3c01.jpeg

48de6a23db08cc178e71e4ac33f32c91.png

如果对你有帮助,帮我点一下在看或转发,欢迎关注我的公众号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1079948.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【开发日记】Docker搭建Maven私服

文章目录 前言1、拉取镜像2、创建本地目录3、启动容器4、访问5、上传依赖6、项目配置私服 前言 Maven私服是一种特殊的远程仓库&#xff0c;它是架设在局域网内的仓库服务&#xff0c;用来代理位于外部的远程仓库&#xff08;中央仓库、其他远程公共仓库&#xff09;。 在公司…

操作系统实验一:计算机资源信 息分析(Windows 2学时)

一、实验目的 通过实验使学生进一步了解操作系统使用的计算机软硬件环境,掌握进程、线程、内存、文件等基本概念,获得某计算机中的软硬件资源信息。基本能达到下列具体的目标: 掌握获取的计算机硬件信息的方法。掌握获取计算机安装的操作系统信息的方法,分析安装的操作系统…

mybatis逆向工程

目录 第一章、mybatis逆向工程1.1&#xff09;Generator.xml配置文件1.2&#xff09;pom文件中添加mybatis代码自动生成插件1.3&#xff09;双击红色选中命令&#xff0c;生成相关文件</font>1.4&#xff09;成功生成mapper和model&#xff0c;加上注解 友情提醒 先看文…

自动化模式下,企业全面预算管理的提升

近年来&#xff0c;经济世界不确定事件的频频发生&#xff0c;让企业开始关注自身的关键财务弱点。企业在财务能力敏捷性提升的方面仍存在一定的差距&#xff0c;而在数字化转型过程中进行的投资不够&#xff0c;将难以推动企业冲出重围&#xff0c;提高前瞻性和自身预测能力。…

【已解决】socket.gaierror: [Errno -3] Temporary failure in name resolution

问题描述 今天在环境迁移的过程中遇到多个问题&#xff0c;包括ModuleNotFoundError: No module named flask&#xff0c;socket.gaierror: [Errno -3] Temporary failure in name resolution以及Downloading: "https://huggingface.co/gyrojeff/YuzuMarker.FontDetection…

2023前端面试题汇总。

一、CSS 1.说一下CSS的盒模型。 在HTML页面中的所有元素都可以看成是一个盒子盒子的组成&#xff1a;内容content、内边距padding、边框border、外边距margin盒模型的类型&#xff1a; 标准盒模型 margin border padding content 2. IE盒模型 margin content(border p…

微服务必学!RedisSearch终极使用指南,你值得拥有!

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是尘缘&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f449;点击这里&#xff0c;就可以查看我的主页啦&#xff01;&#x1f447;&#x…

【ARM Coresight 系列文章 9.1 -- ITM 仪器化跟踪宏单元详细介绍】

文章目录 1.1 ITM 介绍1.1.1 ITM 功能介绍1.1.2 Cortex-M ITM 的地址范围1.2 ITM 使用1.2.1 ITM 寄存器介绍1.2.2 Cortex-M7 ITM 代码示例1.2.3 Cortex-M33 ITM 代码示例1.1 ITM 介绍 在debug 调试阶段通常都是使用 printf(printk) 来进行进行 log 输出,然后定位问题。那么如…

“Python+”集成技术高光谱遥感数据处理与机器学习深度应用丨高光谱数据预处理-机器学习-深度学习-图像分类-参数回归等12个专题

目录 第一章 高光谱数据处理基础 第二章 高光谱开发基础&#xff08;Python&#xff09; 第三章 高光谱机器学习技术&#xff08;python&#xff09; 第四章 典型案例操作实践 更多应用 本教程提供一套基于Python编程工具的高光谱数据处理方法和应用案例。 涵盖高光谱遥感…

C++ Primer (第五版)-第十二章 动态内存

文章目录 序言12.1 动态内存和智能指针shared_ptr类make_shared函数shared_ptr的拷贝和赋值shared_ptr 自动销毁所管理的对象shared_ptr 还会自动释放相关联的内存定义 StrBlob类直接管理内存指针值和delete动态对象的生存期在知道被释放时为止shared_ptr和new结合使用不要混合…

AD7606模块

了解一下ad7606模块,并学习制作一个。 认识AD7606 先了解一下关元AD7606的信息。&#xff08;芯片手册的内容&#xff09; AD7606 采用 5V 单电源供电&#xff0c;不再需要正负 双电源&#xff0c;并支持真正10V 或5V 的双极性信号输。所有的通道均能以高达 200 kSPS 的速率进…

JVM第二讲:JVM 基础 - 字节码详解

JVM 基础 - 字节码详解 本文是JVM第二讲&#xff0c;JVM 基础-字节码详解。源代码通过编译器编译为字节码&#xff0c;再通过类加载子系统进行加载到JVM中运行。 文章目录 JVM 基础 - 字节码详解1、多语言编译为字节码在JVM运行2、Java字节码文件2.1、Class文件的结构属性2.2、…

基于保密信息学科平台系统

目录 前言 一、技术栈 二、系统功能介绍 用户信息管理 教师信息管理 学科动态管理 文献资源管理 征订目录管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步…

注解和依赖注入框架

依赖注入是一种比较流行的设计模式&#xff0c;在 Android 开发中有很多实用的依赖注入框架&#xff0c;可以帮助开发人员少些样板代码&#xff0c;达到各个类之间解耦的目的。 1 注解 从 JDK 5 开始&#xff0c;Java 增加了注解&#xff08;Annotation&#xff09;&#xff…

Maven系列第2篇:安装、配置、mvn运行过程详解

maven系列目标&#xff1a;从入门开始开始掌握一个高级开发所需要的maven技能。 这是maven系列第2篇。 本文主要内容 linux中安装maven window中安装maven mvn命令运行的原理 maven配置设置 本篇环境 jdk1.8 maven3.6.2 我们要写java代码&#xff0c;需要安装jdk&…

Zend Framework 3.1.3 gadget chain

前言 在推特上的PT SWARM账号发布了一条消息。 一个名为Zend Framework的php框架出现了新的gadget chain&#xff0c;可导致RCE。笔者尝试复现&#xff0c;但失败了。所幸&#xff0c;我基于此链&#xff0c;发现在这个框架的最新版本中的另一条链。 复现过程 这里使用vscod…

利达卓越:关注环保事业,持续赋能科技

随着全球环境问题的日益突出,绿色金融作为一种新兴的金融模式逐渐受到各国的重视。绿色金融是指在金融活动中,通过资金、信贷和风险管理等手段,支持环境友好和可持续发展的项目和产业。绿色金融的出现是为了应对气候变化、资源短缺、污染问题等现实挑战,促进经济的绿色转型和可…

【融合ChatGPT等AI模型】Python-GEE遥感云大数据分析、管理与可视化教程

详情点击公众号链接&#xff1a;【融合ChatGPT等AI模型】Python-GEE遥感云大数据分析、管理与可视化教程 第一&#xff1a;基础 1、Earth Engine平台及应用、主要数据资源 2、Earth Engine遥感云重要概念、数据类型与对象等 3、JavaScript与Python遥感云编程比较与选择 4、…

南美哥伦比亚市场最全分析开发攻略,收藏一篇就够了

哥伦比亚作为南美洲最大的经济体之一&#xff0c;其外贸市场潜力巨大&#xff0c;吸引了越来越多的国际企业寻求商机。哥伦比亚跟中国的贸易往来也是非常的密切&#xff0c;今天就来分享一下如何开发南美比较重要的国家哥伦比亚&#xff0c;文章略长&#xff0c;建议大家点赞收…

【RocketMQ】(十一)Dledger模式下的日志复制

RocketMQ在开启Dledger时&#xff0c;使用DLedgerCommitLog&#xff0c;其他情况使用的是CommitLog来管理消息的存储。在Dledger模式下&#xff0c;消息写入时Leader节点还需要将消息转发给Follower节点&#xff0c;有过半的节点响应成功&#xff0c;消息才算写入成功。 Leade…