Go的内存逃逸

news2025/1/30 12:50:29
Go的内存逃逸

内存逃逸是 Go 语言中一个重要的概念,指的是本应分配在栈上的变量被分配到了堆上。栈上的变量在函数结束后会自动回收,而堆上的变量需要通过垃圾回收(GC)来管理,因此内存逃逸会增加 GC 的压力,影响程序性能。
在这里插入图片描述


1. 什么是内存逃逸?

内存逃逸是指本应分配在栈上的变量,由于某些原因被分配到了堆上。栈上的变量在函数结束后会自动回收,而堆上的变量需要通过垃圾回收(GC)来管理。

栈和堆的区别
    • 分配和回收速度快。
    • 变量生命周期与函数绑定,函数结束后自动回收。
    • 适合存储局部变量和小型数据。
    • 分配和回收速度较慢。
    • 变量生命周期不固定,需要 GC 管理。
    • 适合存储大型数据或需要跨函数共享的数据。

2. 内存逃逸的影响

内存逃逸会增加 GC 的压力,影响程序性能:

  • 性能开销:堆上的变量需要通过 GC 回收,增加了额外的性能开销。
  • 延迟增加:GC 的执行可能会导致程序暂停(STW),增加延迟。

3. 内存逃逸的发生条件

以下是一些常见的内存逃逸场景:

3.1 方法内返回局部变量指针
  • 原因:局部变量的指针被返回,导致其生命周期超出函数范围。
package main

import "fmt"

func foo() *int {
    x := 42
    return &x // x 逃逸到堆上
}

func main() {
    p := foo()
    fmt.Println(*p) // 输出: 42
}
3.2 向 channel 发送指针数据
  • 原因:指针数据被发送到 channel,可能导致其生命周期超出当前函数。
package main

import "fmt"

func foo(ch chan *int) {
    x := 42
    ch <- &x // x 逃逸到堆上
}

func main() {
    ch := make(chan *int, 1)
    foo(ch)
    p := <-ch
    fmt.Println(*p) // 输出: 42
}
3.3 在闭包中引用包外的值
  • 原因:闭包中引用的外部变量需要延长其生命周期。
package main

import "fmt"

func foo() func() int {
    x := 42
    return func() int {
        return x // x 逃逸到堆上
    }
}

func main() {
    f := foo()
    fmt.Println(f()) // 输出: 42
}
3.4 在 slice 或 map 中存储指针
  • 原因:slice 或 map 中存储的指针可能导致其生命周期超出当前函数。
package main

import "fmt"

func foo() []*int {
    x := 42
    return []*int{&x} // x 逃逸到堆上
}

func main() {
    s := foo()
    fmt.Println(*s[0]) // 输出: 42
}
3.5 切片(扩容后)长度太大
  • 原因:切片扩容后,数据可能被重新分配到堆上。
package main

import "fmt"

func foo() {
    s := make([]int, 0, 10)
    for i := 0; i < 10000; i++ {
        s = append(s, i) // s 可能逃逸到堆上
    }
    fmt.Println(len(s)) // 输出: 10000
}

func main() {
    foo()
}
3.6 在 interface 类型上调用方法
  • 原因:interface 类型的动态分发可能导致变量逃逸。
package main

import "fmt"

type MyInterface interface {
    DoSomething()
}

type MyStruct struct {
    x int
}

func (m *MyStruct) DoSomething() {
    fmt.Println(m.x)
}

func foo() MyInterface {
    x := 42
    return &MyStruct{x} // x 逃逸到堆上
}

func main() {
    obj := foo()
    obj.DoSomething() // 输出: 42
}

Mermaid 流程图

以下是内存逃逸的流程图:

变量定义
是否逃逸?
分配到堆上
分配到栈上
GC 管理
函数结束后自动回收

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

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

相关文章

StarRocks BE源码编译、CLion高亮跳转方法

阅读SR BE源码时&#xff0c;很多类的引用位置爆红找不到&#xff0c;或无法跳转过去&#xff0c;而自己的Linux机器往往缺乏各种C依赖库&#xff0c;配置安装比较麻烦&#xff0c;因此总体的思路是通过CLion远程连接SR社区已经安装完各种依赖库的Docker容器&#xff0c;进行编…

Vue 响应式渲染 - 待办事项简单实现

Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue 响应式渲染 - 待办事项简单实现 目录 待办事项简单实现 页面初始化 双向绑定的指令 增加留言列表设置 增加删除按钮 最后优化 总结 待办事项简单实现 页面初始化 对页面进行vue的引入、创建输入框和按钮及实例化V…

SpringBoot基础概念介绍-数据源与数据库连接池

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 毛毛张今天介绍的SpringBoot中的基础概念-数据源与数据库连接池&#xff0c;同时介绍SpringBoot整合两种连接池的教程 文章目录 1 数据库与数据库管理系统2 JDBC与数…

Microsoft Visual Studio 2022 主题修改(补充)

Microsoft Visual Studio 2022 透明背景修改这方面已经有很多佬介绍过了&#xff0c;今天闲来无事就补充几点细节。 具体的修改可以参考&#xff1a;Microsoft Visual Studio 2022 透明背景修改&#xff08;快捷方法&#xff09;_material studio怎么把背景弄成透明-CSDN博客文…

(done) ABI 相关知识补充:内核线程切换、用户线程切换、用户内核切换需要保存哪些寄存器?

由于操作系统和编译器约定了 ABI&#xff0c;如下&#xff1a; 编译器在对 C 语言编译时&#xff0c;会自动 caller 标注的寄存器进行保存恢复。保存的步骤通常发生在进入函数的时候&#xff0c;恢复的步骤通常发生在从函数返回的时候。 内核线程切换需要保存的寄存器&#…

Linux 多路转接select

Linux 多路转接select 1. select select() 是一种较老的多路转接IO接口&#xff0c;它有一定的缺陷导致它不是实现多路转接IO的最优选择&#xff0c;但 poll() 和 epoll() 都是较新版的Linux系统提供的&#xff0c;一些小型嵌入式设备的存储很小&#xff0c;只能使用老版本的…

【实践案例】使用Dify构建文章生成工作流【在线搜索+封面图片生成+内容标题生成】

文章目录 概述开始节点图片封面生成关键词实时搜索主题参考生成文章详情和生成文章标题测试完整工作流运行测试结果 概述 使用Dify构建文章生成工作流&#xff0c;使用工具包括&#xff1a;使用 Tavily 执行的搜索查询&#xff0c;使用Flux生成封面图片&#xff0c;使用Stable…

Web3 如何赋能元宇宙,实现虚实融合的无缝对接

随着技术的飞速发展&#xff0c;元宇宙作为一个未来数字世界的概念&#xff0c;正在吸引全球范围内的关注。而 Web3 技术的兴起&#xff0c;为元宇宙的实现提供了强大的支撑。Web3 是基于区块链技术的去中心化网络&#xff0c;它在改变互联网的同时&#xff0c;也推动着虚拟世界…

LangChain的开发流程

文章目录 LangChain的开发流程开发密钥指南3种使用密钥的方法编写一个取名程序 LangChain表达式 LangChain的开发流程 为了更深人地理解LangChain的开发流程&#xff0c;本文将以构建聊天机器人为实际案例进行详细演示。下图展示了一个设计聊天机器人的LLM应用程序。 除了Wb服务…

电商系统-用户认证(四)Oauth2授权模式和资源服务授权

本文章介绍&#xff1a;Oauth2.0 常见授权模式&#xff0c;资源服务授权 。 准备工作 搭建认证服务器之前&#xff0c;先在用户系统表结构中增加如下表结构&#xff1a; CREATE TABLE oauth_client_details (client_id varchar(48) NOT NULL COMMENT 客户端ID&#xff0c;主…

[答疑]DDD伪创新哪有资格和仿制药比

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 远航 2025-1-24 10:40 最近的热门话题仿制药&#xff0c;想到您经常批评的伪创新&#xff0c;这两者是不是很像&#xff1f; UMLChina潘加宇 伪创新哪有资格和仿制药比。 仿制药的…

图漾相机——Sample_V1示例程序

文章目录 1.SDK支持的平台类型1.1 Windows 平台1.2 Linux平台 2.SDK基本知识2.1 SDK目录结构2.2 设备组件简介2.3 设备组件属性2.4 设备的帧数据管理机制2.5 SDK中的坐标系变换 3.Sample_V1示例程序3.1 DeviceStorage3.2 DumpCalibInfo3.3 NetStatistic3.4 SimpleView_SaveLoad…

系统架构设计师教材:信息系统及信息安全

信息系统 信息系统的5个基本功能&#xff1a;输入、存储、处理、输出和控制。信息系统的生命周期分为4个阶段&#xff0c;即产生阶段、开发阶段、运行阶段和消亡阶段。 信息系统建设原则 1. 高层管理人员介入原则&#xff1a;只有高层管理人员才能知道企业究竟需要什么样的信…

Kafka 深入客户端 — 事务

Kafka 事务确保了数据在写入Kafka时的原子性和一致性。 1 幂等 幂等就是对接口的多次调用所产生的结果和调用一次是一致的。 Kafka 生产者在进行重试的时候可能会写入重复的消息&#xff0c;开启幂等性功能后就可以避免这种情况。将生产者客户端参数enable.idempotence设置为…

ZZNUOJ(C/C++)基础练习1011——1020(详解版)

1011 : 圆柱体表面积 题目描述 输入圆柱体的底面半径r和高h&#xff0c;计算圆柱体的表面积并输出到屏幕上。要求定义圆周率为如下宏常量 #define PI 3.14159 输入 输入两个实数&#xff0c;表示圆柱体的底面半径r和高h。 输出 输出一个实数&#xff0c;即圆柱体的表面积&…

Baklib探索内容中台的核心价值与实施策略

内容概要 在数字化转型的背景下&#xff0c;内容中台逐渐成为企业数字化策略中的关键组成部分。内容中台是一个集成的内容管理体系&#xff0c;旨在打破信息孤岛&#xff0c;使内容能够在各个业务部门和平台之间高效流通。这种管理体系不仅能够提升内容的生产效率&#xff0c;…

网络安全攻防实战:从基础防护到高级对抗

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 在信息化时代&#xff0c;网络安全已经成为企业、政府和个人必须重视的问题。从数据泄露到勒索软件攻击&#xff0c;每一次…

论文阅读(十三):复杂表型关联的贝叶斯、基于系统的多层次分析:从解释到决策

1.论文链接&#xff1a;Bayesian, Systems-based, Multilevel Analysis of Associations for Complex Phenotypes: from Interpretation to Decision 摘要&#xff1a; 遗传关联研究&#xff08;GAS&#xff09;报告的结果相对稀缺&#xff0c;促使许多研究方向。尽管关联概念…

“““【运用 R 语言里的“predict”函数针对 Cox 模型展开新数据的预测以及推理。】“““

主题与背景 本文主要介绍了如何在R语言中使用predict函数对已拟合的Cox比例风险模型进行新数据的预测和推理。Cox模型是一种常用的生存分析方法&#xff0c;用于评估多个因素对事件发生时间的影响。文章通过具体的代码示例展示了如何使用predict函数的不同参数来获取生存概率和…

Oracle Primavera P6 最新版 v24.12 更新 1/2

目录 引言 P6 PPM 更新内容 1. 在提交更新基线前预览调整 2. 快速轻松地取消链接活动 3. 选择是否从 XER 文件导入责任经理 4. 提高全局变更报告的清晰度 5. 将整个分层代码值路径导出到 CPP 6. 里程碑活动支持所有关系类型 6. 时间表批准 7. 性能改进 8. 安装改进 …