Unity优化之GC——(一)认识堆(heap)&栈(stack)

【Unity】Unity内存管理与优化(一)内存域、堆栈、垃圾回收、内存泄漏、内存碎片 Unity内存管理 在游戏开发的世界中,程序的优劣与内存的使用有着密不可分的关系。从很多方面来说Unity对于内存的使用并不是最优解,正因为如此,Unity的内存管理与优化就显得尤为重要。 内存域 垃圾回收 内存碎片 运行时垃圾回收 多线程垃圾回收 分析内存 分析内存消耗 分析内存效率 内存管理性能增强 垃圾回收策略 手动JIT编译 值类型和引用类型 传值和传引用 结构体是值类型 数组和引用类型 字符串是不可变的引用类型 字符串连接 StringBuilder 字符串格式化 拆装箱 数据布局的重要性 U 阅读详情

尽管在.NET framework 下我们并不需要担心内存管理和垃圾回收(GarbageCollection),但是我们还是应该了解它们,以优化我们的应用程序。 
同时还需要具备一些基础的内存管理工作机制的知识,这样有助于解释日常程序编写中的变量的行为。 
本文将学习和理解堆和栈的基本知识,变量类型以及为什么一些变量能够按照它们自己的方式工作。

在.NET framework环境下,当我们执行代码时,内存中有两个地方用来存储这些代码:堆和栈。

·Question1:堆和栈有什么不同?

    【申请速度】
    ·堆的申请速度较慢,容易产生内存碎片,但是用起来比较方便。
    ·而栈的申请速度较快,但却不受程序员的控制。
    【申请大小】
    ·栈申请的容量较小1-2M,堆申请大小虽受限于系统中有效的虚拟内存,但较大
    【存储内容】
    ·栈负责保存我们代码执行或调用的路径,而堆则负责保存对象或者说数据的路径。

可以将栈想象成一堆从顶向下堆叠的盒子。每当调用一次方法是,我们应将应用程序中所要发生的事情记录在栈顶的一个盒子中。而我们每次只能够使用栈顶的那个盒子。当我们栈顶的盒子被使用完之后,或者方法执行完毕之后,我们将抛开这个盒子然后继续使用栈顶上的新盒子。 
堆的工作原理比较相似,但大多数时候堆被用作保存信息而非保存执行路径,因此能够在任意时间被访问。 
与栈相比堆没有任何访问限制,堆就像一个仓库,存储着我们使用的各种对象等信息,而栈就像储物柜里堆叠的鞋盒,我们只能从最顶层的盒子开始取, 直到发现那只最适合的。 
和栈不同的是,堆中存储的信息在被调用完毕不会立即被清理掉。  

这里写图片描述

 

栈是自行维护的,也就是说内存自动维护栈,当栈顶的内容不再被使用,该内容将会被跑出。相反,堆需要考虑垃圾回收。

·Question2:堆和栈里有些什么?

当我们的代码执行的时候,堆和栈中主要放置了四种类型的数据:

    值类型(Value Type)
    引用类型(Reference Type)
    指针(Pointer)
    指令(Instruction)

1.值类型 
在C#中,所有被声明为一下类型的事物被称为值类型:

bool
byte
char
decimal
double
enum
float
int
long
sbyte
struct
unit
ulong
ushort


2.引用类型:

所有被声明为一下类型的事物被称为引用类型

class
interface
delegate
object
string
StringBuilder


3.指针

在内存管理方案中放置的第三种类型就是类型引用,引用通常就是一个指针。指针或引用是不同于引用类型的,这是因为当我们说某个事物是一个引用类型时就意味着我们是通过指针来访问它的。指针是一块内存空间,而它指向另一个内存空间。

这里写图片描述

大白话:

    对于引用类型而言,其内存地址(指针)存放在栈上
    其实际内容则由栈上的地址索引存储在堆上
 

4.指令

如何决定放哪? 
这里有一条黄金规则: 
1.引用类型总是放在堆中。 
2.值类型和指针总是放在他们被声明的地方。


就像前面提到的那样,栈是负责保存我们的代码执行或调用时的路径。当我们的代码开始调用一个方法时,将放置一段编码指令(在方法中)到栈上,紧接着放置方法的参数,然后代码执行到方法中被“压栈”至栈顶的变量位置。通过以下的例子很容易理解:

下面是一个方法:

public int PlusSix(int paramValue)
{
    int result;
    result = paramValue + 6;
    return result;
}


现在就来看看在栈顶发生了些神马。

首先方法入栈(只包含需要执行的逻辑字节,即执行该方法的指令,而非方法体内的数据),紧接着是方法的参数入栈。

 

接着,控制(即执行方法的线程)被传递到堆栈中PlusSix()的指令上,

 

当方法执行时,我们需要在栈上为“result”变量分配一些内存,

方法执行完成,然后方法的结果被返回。

通过将指针指向PlusSix()方法曾使用的可用的内存地址,所有栈上的该该方法所使用的内存都被清空,且程序将自动回到栈上最初的方法调用的位置(本例中不会看到)。


在这个例子中,我们的“result”变量是被放置在栈上的,事实上,当值类型数据在方法体重被声明时,它们都是被放置在栈上的。 
值类型数据有时也被放置在堆上。 
记住这条规则——值类型总是放在它们被声明的地方。好滴,如果一个值类型数据在方法体外被声明,而且存在于一个引用类型中,那么他将被堆中的引用类型所取代。

来看另外一个例子:

假如我们有这样一个MyInt类:

public class MyInt
{
    public int MyValue;
}



然后执行下面的方法:

public MyInt PlusSix(int praramValue)
{
    MyInt result = new MyInt();
    result.MyValue = praramValue + 6;
    return result;
}


就像前面提到的,方法以及方法的参数被放置到栈上,接下来,控制被传递到堆栈中的PlusSix()的指令上。

接着会出现一些有趣的现象……

因为“MyInt”是一个引用类型,它将被放置在堆上,同时在栈上生成一个指向这个堆的指针引用。

 

在PlusSix()方法执行之后,我们将清空刚刚使用的栈顶部分。

 

我们将剩下孤独的MyInt对象在堆中(栈中将不会存在任何指向 MyInt对象 的指针!)

这就是垃圾回收器(后简称GC)起作用的地方。 
当我们的程序达到了一个特定的内存阈值,我们需要更多的堆空间的时候,GC开始起作用。 
GC将停止所有正在运行的线程,找出堆中存在的所有不再被主程序访问的对象,并删除它们。 
然后GC会重新组织堆中所有剩下的对象来节省空间,并调整栈和堆中所有与这些对象相关的指针。 
你肯定会想到这个过程非常耗费性能,所以这是你就会知道为什么我们需要如此重视栈和堆里有些什么,特别是在需要编写提高性能的代码是。

太棒了,但它是如何影响我的?

GoodQuestion!

当我们使用引用类型时,我们实际上是在处理该类型的指针,而非该类型本身。当我们使用值类型是,我们是在使用值类型本身。
--------------------- 
作者:qq_26276097 
来源:优快云 
原文:https://blog.youkuaiyun.com/qq_26276097/article/details/75578886 
版权声明:本文为博主原创文章,转载请附上博文链接!

Unity学习(C#)——堆和栈 堆和栈: 我们把内存分为堆空间和栈空间 栈空间小,读取速度块 堆空间大,读取速度慢 栈:数据只能从顶端插入和删除,把数据放入栈为入栈,从栈顶删除数据称为出栈。(相当于薯片的取放,最先放进去的最后出) 堆:一块内存区域,堆里面的内存可以以任意顺序存入和删除。 GC(garbage collector)垃圾回收器 CLR的GC是内存管理机制,我们写程序不需要关系内存的使用,CLR帮我们做了。 类型被分为两种 值类型和引用类型 值类型(如int)只需要单独的内存,用于存储实际的数据。放在栈中 引用类型(如 str 阅读详情

相关推荐

Unity内存优化实战:深度解析Reserved Unity内存构成与治理策略

内存管理是游戏开发中的核心性能优化领域,尤其在Unity引擎中,内存的分配与回收机制直接影响应用的流畅度与稳定性。其原理涉及托管堆、本机分配及垃圾回收等底层机制,通过高效的内存管理,开发者能够显著提升应用性能并降低崩溃风险。在技术价值层面,深入理解内存构成有助于精准定位性能瓶颈,实现从根源上减少内存占用与波动。典型的应用场景包括移动端高性能游戏、复杂UI界面以及频繁对象创建销毁的实时交互系统。本文聚焦于Unity中的Reserved Unity内存,通过剖析其内部构成如托管堆与GC机制,并结合对象池化、增量

weixin_33714884的博客 316

【Unity】Unity中Stack堆栈的使用方法(UI面板)

堆栈(Stack)代表了一个后进先出的对象集合。 当需要对各项进行后进先出的访问时,则使用堆栈。 当在列表中添加一项,称为推入元素, 增加对象时要压入(push) 当从列表中移除一项时,称为弹出元素。 删除对象时要弹出(pop) Stack 类的方法和属性 Count,代表了Stack中的元素个数 Clear(),清除所有Stack中的元素 Contains(Obj),判断obj(代表元素)是否存在于stack中 Peek(),返回在 Stack 的顶部的对象,但不移除它 Pop(),

好吃的和好看的都需要用实力来争取 5663

Unity托管内存优化:从GC原理到实战避坑指南

在Unity游戏开发中,内存管理是影响性能稳定性的核心技术环节。托管内存作为C#运行时自动管理的部分,其核心机制依赖于垃圾回收(GC)自动清理不再使用的对象。理解GC的工作原理,特别是Mono与IL2CPP两套运行时在回收算法上的差异,是进行有效优化的基础。其技术价值在于,通过减少不必要的内存分配与GC触发频率,能够显著提升游戏帧率稳定性,避免卡顿与闪退。在实际应用场景中,高频的字符串拼接、不当的闭包使用、意外的装箱操作以及LINQ查询等,都会在不知不觉中产生大量托管堆分配,成为性能杀手。本文聚焦Unity

weixin_34364071的博客 414

【Unity3D数据集合】(四)堆栈Stack和队列Queue学习

推荐阅读 优快云主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 在日常开发中,常常会用到数据集合,那么数据集合是什么呢,数据集合也没有想象中那么复杂。 数据集合就是专门用来存储数据、检索数据,以及对数据一系列操作的类。 这些类有:ArrayList数组、List列表、Queue队列、Dictionary字典、Hashtable哈希表、S.

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 4906

Unity中Protobuf的GC优化实战:对象池与内存管理策略

在Unity游戏开发中,GC(垃圾回收)是影响性能的关键因素之一,尤其当项目涉及大量网络数据传输或复杂状态同步时。GC机制通过自动回收不再使用的内存来管理托管堆,但其回收过程可能导致主线程卡顿,影响游戏流畅度。为减少GC压力,开发者需要从内存分配原理入手,优化短期小对象的创建与销毁频率。对象池技术是解决这一问题的核心方案,它通过复用已有对象而非频繁新建,显著降低托管堆的分配压力。结合序列化技术如Protobuf,可以在网络通信中实现高效数据编码,但需注意其默认用法可能引发额外GC问题。本文聚焦于Unity环

cucanqi9387的博客 612

Unity垃圾回收优化实战:从原理到性能调优全解析

在实时应用开发中,内存管理是保障性能稳定的核心技术。垃圾回收(GC)作为自动内存管理机制,通过追踪对象引用关系自动释放未使用内存,解放开发者手动管理负担。其核心价值在于防止内存泄漏,但不当使用会引发性能卡顿,尤其在游戏、VR等帧率敏感场景。理解托管堆与非托管堆的差异、GC触发时机及不同运行时(如IL2CPP与Mono)的影响,是优化基础。通过对象池、字符串操作优化、增量式GC等工程实践,可有效减少GC频率与卡顿。本文聚焦Unity开发中的GC问题,结合性能分析与实战策略,帮助开发者实现流畅体验。

weixin_34008933的博客 353

Unity GC优化学习(一):认识堆(heap)&栈(stack)

Unity GC优化学习(一):认识堆(heap)&栈(stack) 尽管在.NET framework 下我们并不需要担心内存管理和垃圾回收(GarbageCollection),但是我们还是应该了解它们,以优化我们的应用程序。同时还需要具备一些基础的内存管理工作机制的知识,这样有助于解...

qq_38267028的博客 621

Unity GC Alloc性能优化实战:从Profiler定位到源码修复

GC Alloc(垃圾回收分配)是Unity中影响帧率稳定性的核心托管内存问题,源于C#脚本在运行时对托管堆的频繁小规模分配。其原理在于.NET运行时对string拼接、泛型集合扩容、struct装箱及协程状态机等操作的隐式堆分配机制。技术价值体现在避免主线程停顿、降低GC触发频率、提升真机流畅度。典型应用场景包括UI列表滚动卡顿、背包界面加载延迟、战斗结算卡顿等高频交互模块。本文聚焦Unity Profiler中GC Alloc数据的精准下钻方法与四类高频陷阱的无痛替换方案,覆盖字符串拼接、List<T>

weixin_29534421的博客 264

Unity内存管理和GC学习

关于内存管理相关内容的学习

qq_49394155的博客 965

【从零开始入门unity游戏开发之——C#篇04】栈(Stack)和堆(Heap),值类型和引用类型,以及特殊的引用类型string,垃圾回收( GC)

C# 中的变量类型分为值类型和引用类型。值类型直接存储数据本身,通常存储在栈上,包括基本数据类型如 int、float 等,以及结构体和枚举。引用类型则存储数据的引用(内存地址),实际数据存储在堆上,包括类、数组、委托和字符串等。值类型赋值时会复制数据,而引用类型赋值时复制引用,多个变量可能指向同一对象。字符串(string)是特殊的引用类型,虽然它属于引用类型,但其行为在某些方面类似于值类型,例如在重新赋值时不会影响其他引用同一字符串的变量。C# 通过栈和堆的内存管理机制,平衡了程序的性能和灵活性。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 2542

Unity内存优化--深入Android的内存优化一

mmap 增长 =IL2CPP 运行时 native 内存增长等手动分配未释放→ 检查你项目的Unmanaged 非托管 内存 分配器IL2CPP托管堆扩张(C# 对象积累)→ 优化对象池使用,减少 GC 压力Unity原生资源(Texture、Mesh 等)未Destroy→ 战斗结束时清理资源。

蛰伏--当你不够强大时,就不要放弃努力 148

Unity GC性能优化实战:从原理到工具,彻底解决游戏卡顿与内存问题

在游戏开发中,内存管理是影响性能的关键因素,而垃圾回收机制则是其核心组成部分。GC通过自动回收不再使用的内存来防止内存泄漏,但其回收过程会占用CPU时间,可能导致程序卡顿。在Unity开发中,理解GC的工作原理对于优化性能至关重要,尤其是在处理高频数据交互和动态资源生成时。通过分析GC的触发机制和内存分配模式,开发者可以采取有效的优化策略,如使用对象池和避免不必要的内存分配,从而提升游戏的流畅度。本文聚焦于Unity中的GC问题,探讨如何通过工具定位和代码优化来解决常见的性能瓶颈,特别是在移动端开发中,如处

weixin_30596343的博客 505

极化码理论及算法研究4-巴氏参数、GA算法以及matlab仿真

目录 (如要找其他内容,欢迎访问我的主页寻找) #前言 #极化码概述 #极化码定义 #极化码编码 #极化码译码 #5G标准中极化码的编译码概述 #5G标准中极化码的编码 #5G标准中极化码的译码 #总结 极化码编码 ...

1万+

[WIP] Unity经验汇总-【C#】

Awake与Start Awake是在场景被加载的时候被调用 Start是第一次Update/FixedUpdate调用之前被调用 执行顺序:Awake–&gt;OnEnable-&gt;Start FixedUpdate会以固定时间间隔更新 可做逻辑帧更新 反射的实现原理 审查元数据并收集关于它的类型信息的能力。实现原理:在运行时根据程序集及其中的类型得到元数据。下面是实现步骤: ...

一生做游戏 382

microduck复刻实战:强化学习机器人从仿真训练到真机部署全攻略

强化学习是智能体通过与环境交互试错来学习最优策略的机器学习范式,在机器人控制领域,常借助物理仿真环境进行策略训练,以降低真实世界的试错成本。其核心原理是通过奖励信号引导策略网络迭代优化,PPO等算法则在稳定性和样本效率之间取得平衡。仿真训练的价值在于可批量验证控制策略,但仿真与真实硬件之间存在物理参数偏差,需通过域随机化等技术实现迁移。从四足机器人到仿生机器人,这类方案广泛应用于复杂运动控制任务。microduck作为一个典型的强化学习机器人项目,其复刻过程涉及环境搭建、奖励设计、PPO调参及Sim-to-

weixin_29061425的博客 361

MuJoCo柔性体仿真实战:从FlexComp建模到自定义模型导入

柔性体仿真是机器人交互研究中不可或缺的一环,MuJoCo作为高精度物理求解器,凭借高效的求解速度与批量并行能力,成为强化学习与软体抓取任务的热门选择。其FlexComp机制将连续材料离散为粒子-约束系统,以较低建模成本模拟布料、软组织等形变行为,相比Gazebo等平台更具实时性与可扩展性。技术价值体现在自定义柔性体建模与导入流程中:通过XML配置网格密度、间距与材料参数,即可生成贴合任务需求的软体垫子或硅胶抓手。在柔性抓取、颗粒抓手、医疗仿真等场景中,该方法能快速构建可训练的环境。围绕环境搭建、FlexCo

weixin_29045585的博客 159

Unity脚本优化实战:从CPU、内存到GC的全面性能提升指南

在游戏开发中,性能优化是确保流畅体验的核心技术。其原理在于通过减少CPU计算负担、优化内存管理来提升帧率与响应速度。这项技术的价值在于能够将有限的硬件资源最大化利用,尤其在移动端和大型动态场景中至关重要。应用场景广泛覆盖游戏逻辑更新、物理计算、动画处理以及UI渲染等环节。本文聚焦Unity引擎中的C#脚本优化,深入探讨如何通过缓存高频操作、实现对象池复用以及优化垃圾回收(GC)等实战技巧,系统解决卡顿问题,其中对象池和GC优化是提升性能的关键热词。

agcozdwdfvds08078的博客 341

阿里云导出的镜像raw转换成vmdk格式工具

阿里云导出的镜像raw转换成vmdk格式工具 1.安装java环境,安装教程不介绍了 2.raw2vmdk软件下载: 在我的链接里面: 3.使用 打开cmd.bat软件: java -jar raw2vmdk.jar (原镜像)C:\\images\\raw\\disk.img (转换的镜像)D:\\images\\vmdk\\disk.vmdk 4.vmware打开vmdk文件 ...

3843

Unity内存优化实战:用Heap Explorer精准定位与解决托管堆问题

在Unity游戏开发中,托管堆内存管理是性能优化的核心挑战之一。其原理在于C#的自动垃圾回收机制,不当的内存分配与引用持有会触发GC,导致帧率卡顿,甚至引发内存泄漏导致崩溃。这项技术的价值在于,通过精细的内存控制,开发者能显著提升游戏运行的流畅度与稳定性,尤其在移动端等内存受限平台至关重要。应用场景广泛覆盖从高频小对象分配到资源生命周期管理的各个环节。本文聚焦于Unity Profiler中的Heap Explorer工具,它如同性能手术刀,能深度剖析托管堆,揭示对象分配、引用关系与泄漏根源。通过建立“数据

weixin_34109408的博客 364

从零构建企业级多智能体系统:LangGraph 全流程实战 + 部署指南(含代码与架构图)

> 在大模型应用爆发的今天,如何构建一个可协作、可调试、可部署的多智能体系统?LangGraph 正在成为工程师的新宠。本文从原理剖析、流程建模、代码实战到前后端部署,手把手带你用 LangGraph 构建一个企业级 AI 助理系统,整合财务分析、法务审阅、报告生成与图表可视化等 Agent 模块,全面打通从用户输入到报告输出的全链路闭环。适合有工程思维的 AI 架构师、Agent 研发人员、以及大模型项目实践者。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 3449

注册GitHub时出现Unable to verify your captcha response.Please visit https://docs.github.com/解决方案(持续更新)

本文主要介绍了注册GitHub时出现Unable to verify your captcha response. Please visit https://docs.github.com/articles/troubleshooting-connectivity-problems/#troubleshooting-the-captcha for troubleshooting information.解决方案,希望能对学习使用GitHub的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 8万+

Unity内存碎片化诊断与优化:从原理到实践的全面解决方案

内存管理是游戏开发与软件工程中的核心基础概念,它直接决定了应用程序的运行时性能与稳定性。其原理在于程序运行过程中,内存的分配与释放若缺乏有效管理,会产生大量不连续的小块空闲空间,即内存碎片化,导致即使总空闲内存充足,也无法满足大块连续内存的请求。这一问题的技术价值在于,深刻的内存优化能显著提升应用响应速度、降低卡顿并避免因内存不足引发的崩溃。在Unity游戏开发、移动应用及长期运行的实时系统中,内存碎片化尤为突出,常表现为帧率下降、加载卡顿及闪退。本文聚焦于Unity引擎环境,深入探讨了托管堆与原生堆中碎片

weixin_33922670的博客 441

PHPStorm携手ThinkPHP8:开启高效开发之旅

本文围绕使用 PHPStorm 进行 ThinkPHP8 开发展开,先介绍开发环境搭建与 Xdebug 配置,再阐述 PHPStorm 集成 ThinkPHP8 的步骤,包括项目导入、解释器和服务器配置。还讲解了项目开发基础、数据库操作、高级技巧、调试处理及部署上线等内容,为开发者提供了从环境搭建到项目上线的完整指引,助力高效开展 ThinkPHP8 开发工作。

邓邓子的博客 1544

Unity异步编程性能优化:UniTask深度测试与零GC分配实战指南

在Unity游戏开发中,异步编程是提升应用响应性和管理复杂逻辑的核心技术。其原理是通过非阻塞操作让主线程继续执行,避免卡顿,从而提升用户体验。从早期的协程(Coroutine)到原生的Task,开发者一直在寻找更高效的解决方案。UniTask作为专为Unity设计的异步库,通过值类型(ValueTask)和自定义AsyncMethodBuilder等技术,实现了近乎零GC分配的高性能异步操作,这对于移动端游戏减少垃圾回收卡顿至关重要。在资源加载、UI流程和网络请求等常见应用场景中,合理运用UniTask可以

weixin_33801856的博客 303

9.16华为OD机试真题 新系统 - 矩阵螺旋遍历 (Java/Py/C/C++/Js/Go)

9.16华为OD机试真题 新系统 - 矩阵螺旋遍历 (Java/Py/C/C++/Js/Go)

算法大师! 646

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

上一篇: Unity优化之GC——(二)合理优化Unity的GC
下一篇: SpriteRenderer(场景_UI)和Image(Canvas_UI)的区别
Le_Sam
博客等级 码龄11年 342粉丝 53原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值