golang学习笔记(内存逃逸分析)

golang的内存逃逸

逃逸分析( Escape analysis) 是指由编译器决定内存分配的位置, 不需要程序员指定。 函数中申请一个新的对象。

  • 如果分配在栈中, 则函数执行结束可自动将内存回收;
  • 如果分配在堆中, 则函数执行结束可交给GC( 垃圾回收) 处理;

内存逃逸策略

每当函数中申请新的对象, 编译器会跟据该对象是否被函数外部引用来决定是否逃逸:

  • 如果函数外部没有引用, 则优先放到栈中
  • 如果函数外部存在引用, 则必定放到堆中;

注意, 对于函数外部没有引用的对象, 也有可能放到堆中, 比如内存过大超过栈的存储能力。

逃逸场景分析

指针逃逸

Go可以返回局部变量指针, 这其实是一个典型的变量逃逸案例, 示例代码如下:

package main

type Student struct {
	Name string
	age int
}

func NewStudent(name string, age int) *Student {
	stu := new(Student)
	stu.Name = name
	stu.age = age
	return stu
}
func main()  {
	NewStudent("abcd", 24)
}

函数NewStudent()内部stu为局部变量, 其值通过函数返回值返回, stu本身为一指针, 其指向的内存地址不会是栈而是堆, 这就是典型的逃逸案例。

通过编译参数-gcflags=-m可以查年编译过程中的逃逸分析:
运行结果: 请注意运行结果中出现了escapes to heap,也就是发生了内存逃逸现象。
在这里插入图片描述

栈空间不足逃逸

分析一下下面代码会不会产生内存逃逸现象

package main

type Student struct {
	Name string
	age int
}

func Slice()  {
	s := make([]int, 1000, 1000)
	for index, _ := range s {
		s[index] = index
	}
}
func main()  {
	Slice()
}

上面代码Slice()函数中分配了一个1000个长度的切片, 是否逃逸取决于栈空间是否足够大。 直接查看编译提示, 如下可见并没有发生逃逸:
在这里插入图片描述
但是如果长度扩大10倍呢?那情况会怎么样?

package main

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

结果:
在这里插入图片描述
我们发现当切片长度扩大到10000时就会逃逸。实际上当栈空间不足以存放当前对象时或无法判断当前切片长度时会将对象分配到堆中

动态类型逃逸

很多函数参数为interface类型, 比如fmt.Println(a …interface{}), 编译期间很难确定其参数的具体类型,也人产生逃逸。 如下代码所示:

package main

import "fmt"

func main()  {
	s := "abcd"
	fmt.Println(s)
}

结果:上述代码s变量只是一个string类型变量, 调用fmt.Println()时会产生逃逸。
在这里插入图片描述

闭包引用对象逃逸

相信刷题的同学对这代码是十分的熟悉:

package main

import "fmt"

func Fibonacci() func() int {
	a, b := 0, 1
	return func() int {
		a, b = b, a + b
		return a
	}
}
func main()  {
	res := Fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Printf("Print Result is %d\n" , res())
	}
}

这段代码的运行结果如下:
在这里插入图片描述
但是Fibonacci()函数中原本属于局部变量的a和b由于闭包的引用, 不得不将二者放到堆上, 以致产生逃逸:
在这里插入图片描述

总结

  • 栈上分配内存比在堆中分配内存有更高的效率
  • 栈上分配的内存不需要GC处理
  • 堆上分配的内存使用完毕会交给GC处理
  • 逃逸分析目的是决定内分配地址是栈还是堆
  • 逃逸分析在编译阶段完成

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微软开源 MS-DOS「GitHub 热点速览」

上周又是被「大模型」霸榜的一周&#xff0c;各种 AI、LLM、ChatGPT、Sora、RAG 的开源项目在 GitHub 上“争相斗艳”。这不 Meta 刚开源 Llama 3 没几天&#xff0c;苹果紧跟着就开源了手机端大模型&#xff1a;CoreNet。 GitHub 地址&#xff1a;github.com/apple/corenet 开…

网络安全前置知识-linux操作系统

计算机体系结构 计算机发展历史 计算机组成 计算机硬件组成 1. CPU 原文链接&#xff1a;https://blog.csdn.net/stone_fall/article/details/88414017 一条指令的执行过程分为以下5个周期&#xff1a; 取指令周期&#xff08;Instruction Fetch&#xff0c;IF&#xff…

【Cpp】类和对象

标题&#xff1a;【Cpp】类和对象 水墨不写bug 正文开始&#xff1a; &#xff08;一&#xff09;面向过程与面向对象 面向过程和面向对象是两种不同的编程思想。 面向过程指的是将程序分解成多个步骤&#xff0c;每个步骤都是一个独立的函数&#xff0c;通过函数之间的调用实…

使用OneAPI创建LLM访问API Key

OneAPI 是一个能替代 springdoc-openapi/Swagger 的 API 生产工具&#xff0c;既不需要修改后端代码&#xff0c;也不需要启动应用。 也支持导出 OpenAPI 3.0 协议数据&#xff0c;方便在其他工具中消费。 前面我们介绍了LobeChat需要配置LLM的API访问Key&#xff0c;今天你可…

《架构即未来》读后感

目录 一、引言 二、《架构即未来》读后感 1、主题的简要介绍 2、我的看法和理解 3、作者的优点和传递的信息 4、思想如何适用于当今社会 三、《架构即未来》对于企业发展的影响具体体现在哪些方面&#xff1f; 一、引言 任何一个持续成长的公司最终都需要解决系统、组织…

【讲解下如何解决一些常见的 Composer 错误】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

【Spring AI】09. ETL 管道

文章目录 ETL PipelineAPI 概述入门指南ETL 接口和实现DocumentReaderJsonReaderTextReaderPagePdfDocumentReaderParagraphPdfDocumentReaderTikaDocumentReader DocumentTransformerTextSplitterTokenTextSplitterContentFormatTransformerKeywordMetadataEnricherSummaryMet…

Ftrans文件外发系统 构建安全可控文件外发流程

文件外发系统是企业数据安全管理中的关键组成部分&#xff0c;它主要用于处理企业内部文件向外部传输的流程&#xff0c;确保数据在合法、安全、可控的前提下进行外发。 文件外发系统的主要作用包括&#xff1a; 1、防止数据泄露&#xff1a;通过严格的审批流程和安全策略&…

【强训笔记】day7

NO.1 思路&#xff1a;双指针模拟&#xff0c;begin表示最长数字字符串最后一个字符&#xff0c;而len表示数字字符串的长度&#xff0c;i用来遍历&#xff0c;如果为数字&#xff0c;那么定义j变量继续遍历&#xff0c;直到不为数字&#xff0c;i-j如果大于len&#xff0c;就…

LabVIEW机械臂控制与图像处理示教平台

LabVIEW机械臂控制与图像处理示教平台 随着工业自动化技术的快速发展&#xff0c;工业机器人在制造业中的应用越来越广泛&#xff0c;它们在提高生产效率、降低人工成本以及保证产品质量方面发挥着重要作用。然而&#xff0c;传统的工业机器人编程和操作需要专业知识&#xff…

深入理解vector 【C++】

一、vector的介绍&#xff1a; 1.vector是表示可变大小的顺序容器。 2.就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的&am…

【C++STL详解(五)】--------list的介绍与使用

目录 前言 一、list的介绍 二、list的使用 Ⅰ.默认成员函数 1、构造函数 2、赋值重载 3、析构函数 Ⅱ、容量 1.size() Ⅲ、迭代器与遍历 1.beginend (正向迭代器) 2.rbeginrend (反向迭代器) 3.front 4.back Ⅳ、增删查改 1.push_front 2.pop_front 3.push_b…

Matlab|二阶锥松弛在配电网最优潮流计算中的应用

目录 一、主要内容 二、部分代码 三、程序代码 四、下载链接 一、主要内容 最优潮流计算是电网规划、优化运行的重要基础。首先建立了配电网全天有功损耗最小化的最优潮流计算模型&#xff1b;其次结合辐射型配电网潮流特点建立支路潮流约束&#xff0c;并考虑配电网中的可…

平平科技工作室-Python-步步惊心

一.准备图片 放在 文件夹取名为imgs,分为两种boys和girls 二.编写程序 首先创建一个文件名为index.py 其次编写程序 # coding:utf-8 import sys, time, easygui, os, pygame from pygame.locals import * pygame.init() # 设置窗口显示位置、大小、颜色、标题 os.environ[ …

Go语言的包管理工具go mod与之前的GOPATH有什么区别?

在深入探讨Go语言的包管理工具go mod与之前的GOPATH之间的区别之前&#xff0c;我们首先需要理解这两个概念各自的作用和背景。 GOPATH时代 在Go语言早期版本中&#xff0c;GOPATH是一个非常重要的环境变量。它告诉Go工具链在哪里查找你的Go代码、第三方库以及编译后的二进制…

C#描述-计算机视觉OpenCV(4):图像分割

C#描述-计算机视觉OpenCV&#xff08;4&#xff09;&#xff1a;图像分割 前言用 GrabCut 算法分割图像实例展示 前言 本文中如果有什么没说明的地方&#xff0c;大概率在前文中描述过了。 C#描述-计算机视觉OpenCV&#xff08;1&#xff09;&#xff1a;基础操作 C#描述-计算…

docker 指定根目录 迁移根目录

docker 指定根目录 1、问题描述2、问题分析3、解决方法3.1、启动docker程序前就手动指定docker根目录为一个大的分区(支持动态扩容)&#xff0c;事前就根本上解决根目录空间不够问题3.1.0、方法思路3.1.1、docker官网安装文档3.1.2、下载docker安装包3.1.3、安装docker 26.1.03…

记一次从登录框到前台rce

接口未授权挖掘 在网站未登录的情况下&#xff0c;由于不知道后台接口。唯一办法通过js文件、路径扫描。通过这种收集方式使用burp进行批量扫描&#xff0c;分别探测GET/POST请求。观察响应包跟状态码。判断响应包&#xff0c;确定存在未授权后&#xff0c;再构造数据包。 2 突…

C++ | Leetcode C++题解之第64题最小路径和

题目&#xff1a; 题解&#xff1a; class Solution { public:int minPathSum(vector<vector<int>>& grid) {if (grid.size() 0 || grid[0].size() 0) {return 0;}int rows grid.size(), columns grid[0].size();auto dp vector < vector <int>…

机器学习笔记-18

异常检测问题 异常检测虽然主要用于无监督学习问题上&#xff0c;但是和监督学习问题很相似。 异常检测(Anomaly Detection)&#xff1a;给定正确样本集{ x ( 1 ) , x ( 2 ) . . . x ( n ) x^{(1)},x^{(2)}...x^{(n)} x(1),x(2)...x(n)}&#xff0c;记新样本即要检测的样本为…