IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Golang 内存逃逸 -> 正文阅读

[网络协议]Golang 内存逃逸

一 什么是内存逃逸

????????Golang中,内存的分配有两种方式:堆(Heap)和栈(Stack);栈是计算机内存的特定区域,一般是 CPU 自动分配释放,读写很快,更重要的是不会产生碎片;堆是应用程序在运行的时候请求操作系统分配的,需要申请和释放,会产生碎片。他们直接的区别和联系,见这篇文章:什么是堆?什么是栈?他们之间有什么区别和联系
????????那么什么是内存逃逸呢?简单说,就是指从栈上的分配变为从堆上分配。Go在编译的时候会进行逃逸分析,来决定是放栈上还是放堆上,不逃逸的对象放栈上,可能逃逸的放堆上。

二 逃逸场景

???????? 那么在什么情况下会发生内存逃逸呢?这个就是本篇文章要探讨的。在探讨之前,需要说明的是,验证某个函数的变量是否发生逃逸,我这里使用命名:go run -gcflags "-m -l" (-m 打印逃逸分析信息,-l 禁止内联编译);

1 指针逃逸

????????Go在方法内将局部变量指针返回,如:
package main

type demoStr struct {
	demo string
}

func newDemoStr(v string) *demoStr {
	t := new(demoStr)
	t.demo = v

	return t
}

func main() {
	newDemoStr("This is a test demo")
}
???????? 结果如下:

在这里插入图片描述

2 切片扩容或容量太大,栈空间不足

package main


func main() {
	s1 := make([]int, 1000000, 1000000)
	_ = s1
}
???????? 结果如下:

在这里插入图片描述

3 在 slice 或 map 中存储指针

package main

func main() {
	var x int32 = 10
	var ls []*int32
	ls = append(ls, &x)
}

???????? 结果如下:

在这里插入图片描述

4 发送指针或带有指针的值到 channel 中

package main

func main() {
	ch1 := make(chan int, 1)
	x := 30
	ch1 <- x // x不会发生逃逸,因为它只是复制
	ch2 := make(chan *int, 1)
	y := 30
	py := &y
	ch2 <- py // y 逃逸,因为 y 地址传入了chan中,编译时无法确定什么时候会被接收,所以也无法在函数返回后回收
}

???????? 结果如下:

在这里插入图片描述

5 Interface类型多态

6 闭包引用包外的值

三 如何避免

1 对于少量的数据,使用传值而不是传指针
2 尽量避免使用长度不固定的 slice 切片,因为在编译期无法确定切片长度,只能将切片使用堆分配
3 性能要求比较高且访问频次比较高的函数调用,谨慎使用 interface 调用方法

参考文档

https://zhuanlan.zhihu.com/p/438812101
https://juejin.cn/post/6952177646050639902
https://cloud.tencent.com/developer/article/1732263
https://mp.weixin.qq.com/s?__biz=MzAxMTA4Njc0OQ%3D%3D&mid=2651437818&idx=1&sn=4f1e08a9b73b70c347033778b2d56b82&scene=45#wechat_redirect
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章           查看所有文章
加:2022-04-15 00:40:35  更:2022-04-15 00:46:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:37:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码