Unity性能优化3【内存基础篇】

1.性能、内存管理和垃圾收集的关系

先说结论,内存管理影响着游戏性能,垃圾收集是内存管理的重要部分。

当我们的游戏运行时,它使用内存来存储数据。当不再需要此数据时,存储该数据的内存将被释放,以便可以重复使用。垃圾是指已预留用于存储数据但不再使用的内存的术语。垃圾收集是使内存再次可供重用的进程的名称。 Unity 使用垃圾收集作为管理内存的一部分。如果垃圾收集发生得太频繁或有太多工作要做,我们的游戏可能会表现不佳,这意味着垃圾收集是性能问题的常见原因。

2.Unity内存管理简介

要了解垃圾收集的工作原理以及何时发生,我们必须首先了解 Unity 中内存使用的工作原理。首先,我们必须了解 Unity 在运行其自己的核心引擎代码和运行我们在脚本中编写的代码时使用不同的方法。

Unity 在运行自己的核心 Unity 引擎代码时管理内存的方式称为手动内存管理。这意味着核心引擎代码必须明确说明如何使用内存。手动内存管理不使用垃圾收集,因此本文不会进一步讨论。

Unity 在运行我们的代码时管理内存的方式称为自动内存管理。这意味着我们的代码不需要明确地告诉Unity如何详细地管理内存。 Unity 会帮我们处理这个问题。Unity 中的自动内存管理是这样工作的:

1. Unity可以访问两个内存池:栈和堆(栈用于短期存储小块数据,堆用于长期存储和较大块)

2. 创建变量时,Unity 会从栈或堆中请求一块内存。

3. 只要变量在作用域内(我们的代码仍然可以访问),分配给它的内存就会保留在其中。我们说这个内存已经被分配了,我们将保存在栈内存中的变量描述为栈上的对象,将保存在堆内存中的变量描述为堆上的对象。

4. 当变量超出范围时,不再需要该内存,并且可以将其返回到它来自的池中。当内存返回到其池中时,我们说内存已被释放。一旦它引用的变量超出范围,栈中的内存就会被释放。然而,此时堆中的内存并未被释放,并且仍处于已分配状态,即使它引用的变量超出了范围。

5. 垃圾收集器识别并释放未使用的堆内存。垃圾收集器定期运行以清理堆。

3.栈的分配和释放

栈分配和释放既快速又简单。这是因为栈仅用于在短时间内存储小数据。分配和释放总是以可预测的顺序发生,并且具有可预测的大小。

栈的工作方式类似于栈数据类型:它是元素的简单集合,在本例中是内存块,其中只能按照严格的顺序添加和删除元素。这种简单性和严格性使得它如此之快:当变量存储在栈上时,它的内存只是从栈的“末尾”分配。当栈变量超出范围时,用于存储该变量的内存将立即返回到堆栈以供重用。

4.堆的分配

堆分配比栈分配复杂得多。这是因为堆可用于存储长期和短期数据以及许多不同类型和大小的数据。分配和释放并不总是以可预测的顺序发生,并且可能需要不同大小的内存块。

创建堆变量时,会发生以下步骤:

1. Unity必须检查堆中是否有足够的可用内存。如果堆中有足够的可用内存,则会为变量分配内存。

2. 如果堆中没有足够的可用内存,Unity 会触发垃圾收集器以尝试释放未使用的堆内存。这可能是一个缓慢的操作。如果堆中现在有足够的可用内存,则会为变量分配内存。

3. 如果垃圾回收后堆中没有足够的可用内存,Unity 会增加堆中的内存量。这可能是一个缓慢的操作。然后分配变量的内存。

堆分配可能会很慢,尤其是在必须运行垃圾收集器并且必须扩展堆的情况下

5.垃圾收集期间会发生什么?

当堆变量超出范围时,用于存储它的内存不会立即释放。未使用的堆内存仅在垃圾收集器运行时才被释放

每次垃圾收集器运行时,都会发生以下步骤:

1. 垃圾收集器检查堆上的每个对象。

2. 垃圾收集器搜索所有当前对象引用,以确定堆上的对象是否仍在作用域内。

3. 任何不再在范围内的对象都会被标记为删除。

4. 标记的对象被删除,分配给它们的内存返回到堆。

垃圾收集可能是一项昂贵的操作。堆上的对象越多,它必须做的工作就越多,代码中的对象引用越多,它必须做的工作就越多。

6.垃圾收集何时发生?

三种情况可能导致垃圾收集器运行:

1. 每当请求堆分配而无法使用堆中的可用内存来满足时,垃圾收集器就会运行。

2. 垃圾收集器会不时自动运行(尽管频率因平台而异)。

3.垃圾收集器可以强制手动运行。

垃圾收集可能是一项频繁的操作。每当可用堆内存无法完成堆分配时,就会触发垃圾收集器,这意味着频繁的堆分配和释放可能会导致频繁的垃圾收集。

7.垃圾收集存在的问题

垃圾回收可能出现如下3种类型的问题:

1.垃圾收集可能占用较长的CPU时间。如果垃圾收集器在堆上有很多对象和对象引用,则检查所有这些对象的过程可能会很慢。这可能会导致我们的游戏卡顿或运行缓慢。

2.垃圾收集可能发生在性能尖峰期。如果 CPU 已经在游戏的性能关键部分中努力工作,那么即使垃圾收集带来的少量额外开销也会导致帧速率下降和性能显着变化。

3.垃圾收集可能产生较多的堆碎片。当从堆中分配内存时,根据必须存储的数据大小,从不同大小的块中的可用空间中获取内存。当这些内存块返回到堆时,堆可以分成许多由分配块分隔的小空闲块。这意味着虽然可用内存总量可能很高,但我们无法在不运行垃圾收集器或扩展堆的情况下分配大内存块,因为现有块都不够大。堆碎片有两个后果。第一个是我们的游戏的内存使用量将高于所需的内存使用量,第二个是垃圾收集器将更频繁地运行

8.栈和堆上分配了什么?

在 Unity 中,值类型的局部变量在栈上分配,其他所有变量都在堆上分配。以下代码堆栈分配的示例,因为变量 localInt 既是本地变量又是值类型的。为该变量分配的内存将在该函数完成运行后立即从栈中释放。

void ExampleFunction()
{int localInt = 5;
}

以下代码是堆分配的示例,因为变量 localList 是本地变量,但是引用类型的。当垃圾收集器运行时,为此变量分配的内存将被释放。

void ExampleFunction()
{List localList = new List();
}

9.减少垃圾收集的影响

从控制垃圾收集器的角度,可通过三种方式减少垃圾收集对游戏的影响:

1. 我们可以减少垃圾收集器运行的时间。

2. 我们可以降低垃圾收集器运行的频率。

3. 我们可以故意触发垃圾收集器,以便它在性能不关键的时间运行,例如在加载屏幕期间。

从代码的角度,有三种策略可以帮助我们:

1. 组织代码,减少堆分配和对象引用。堆上的对象越少,要检查的引用越少,这意味着触发垃圾收集时,运行时间会更少。

2. 减少堆分配和释放的频率,特别是在性能关键时刻。更少的分配和释放意味着触发垃圾收集的机会更少。这也降低了堆碎片的风险。

3. 安排垃圾收集的时间,让其可预测且方便的时间发生。这是一种更困难且不太可靠的方法,但当用作整体内存管理策略的一部分时可以减少垃圾收集的影响。

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

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

相关文章

vue-pc 实现内嵌式微信扫码登录(附完整代码)

一、准备工作 1. 注册微信开放平台账号 地址:([https://open.weixin.qq.com/](https://open.weixin.qq.com/)) 2. 申请开发者资质认证: 3. 创建网站应用 4. 查看应用详情,拿到 AppID 、 AppSecret 和 redirect_uri (授…

如何在服务器上部署开源大模型 GLM-4-9B-Chat 并应用到RAG应用中

本地服务器部署开源大模型有一个前提,就是得有 GPU 显卡资源,在我下面的例子中我租用了 autodl 中的算力资源,具体是租用了一张消费级别的 RTX 3090 显卡。 环境配置 操作系统及版本:ubuntu 22.04CUDA 版本: 12.1pyto…

【MATLAB源码-第263期】基于matlab的帝企鹅优化算法(EPO)无人机三维路径规划,输出做短路径图和适应度曲线.

操作环境: MATLAB 2022a 1、算法描述 帝企鹅优化算法(Emperor Penguin Optimizer,简称EPO)是一种基于自然现象的优化算法,灵感来自于帝企鹅在南极极寒环境中的生活习性。帝企鹅是一种群居动物,生活在极端…

再创佳绩 | 竹云荣获“数据要素×”大赛黑龙江分赛一等奖!

近日,由国家数据局、黑龙江省人民政府指导,黑龙江省发改委、黑龙江省数据局主办的2024年“数据要素”大赛黑龙江分赛决赛盛大召开。竹云作为联合单位参与《供热数据资产登记评价中心供热数据要素综合服务平台》项目,荣获绿色低碳赛道一等奖。…

C++ [项目] 愤怒的小鸟

现在才发现C游戏的支持率这么高,那就发几篇吧 零、前情提要 此篇为 制作,由于他没有CSDN,于是由我代发 一、基本介绍 支持Dev-C5.11版本(务必调为英文输入法),基本操作看游戏里的介绍,怎么做的……懒得说,能看懂就看注释,没有的自己猜,如果你很固执……私我吧 …

java-实例化一个List,然后添加数据的方法详解

在Java中,实例化一个 List 并向其中添加数据非常简单。List 是一个接口,因此我们通常使用它的常见实现类 ArrayList 或 LinkedList。以下是一些常见的操作方法: ### 1. 使用 ArrayList 实例化并添加数据 java import java.util.ArrayList; …

基于K8S的StatefulSet部署mysql主从

StatefulSet特性 StatefulSet的网络状态 拓扑状态:应用的多个实例必须按照某种顺序启动,并且必须成组存在,例如一个应用中必须存在一个A Pod和两个B Pod,且A Pod必须先于B Pod启动的场景 存储状态:应用存在多个实例&…

分享Vue3中的一个路由加载函数,基于Glob导入模式,根据路径自动生成路由

哈喽,大家好!我是「励志前端小黑哥」,我带着最新发布的文章又来了! 专注前端领域10年,专门分享那些没用的前端知识! 今天要分享的内容,是一段路由加载的函数代码,这段代码能自动读取…

StringBulider和StringBuffer的底层源码剖析

要深入了解 StringBuffer 和 StringBuilder 的区别,从底层源码的角度来解析,包括它们的创建、扩容机制等,可以参考 JDK 1.8 的源码。 1. AbstractStringBuilder 类 StringBuffer 和 StringBuilder 都继承自 AbstractStringBuilder。…

Three.js实现小米 su7 压缩后的模型加载

Three.js实现小米 su7 压缩后的模型加载 预览: https://threehub.cn/#/codeMirror?navigationThreeJS&classifybasic&idgltfOptLoader import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls.js impo…

复旦大学全球供应链研究中心揭牌,合合信息共话大数据赋能

10月13日,复旦大学全球供应链研究中心(以下简称“中心”)揭牌仪式在复旦大学管理学院政立院区隆重举行。我国的供应链体系庞大复杂,在百年未有之大变局下,保障产业链供应链安全已成为我国的重要战略目标。中心的设立旨…

《Vue3 版本差异》Vue3.5+ 在组件或HTML元素绑定 ref 差异

组件上的 ref,组合式写法的变化; 在 2024.09.03 发布的 v3.5.0 版上新增接口 useTemplateRef; v3.5 之前 代码第 8 行,导入 ref;代码第 10 行,使用 ref 传参为 null,变量名与 第三行 ref 同…

【python】sorted() list.sort()

文章目录 sorted()和list.sort()sorted 函数sorted()根据键对字典排序根据字典的键排序根据字典的值排序将排序结果转换回字典 list.sort() 方法总结 keylambda student: student[age] sorted()和list.sort() 在Python中,sorted 函数和 list.sort() 方法都可以用来…

打造企业数字化转型的未来蓝图:架构蓝图的构建与实施策略深度解析

随着数字经济的蓬勃发展,全球企业正在经历前所未有的变革与挑战。企业的运营模式、客户体验和市场竞争格局都在迅速变化。为了应对这些挑战,企业必须从战略到技术层面进行深度重塑,架构蓝图的构建和实施是数字化转型过程中不可或缺的工具。架…

CSS - grid制作表格

1. grid-template-columns:网格布局中的列的数量,也可以设置列的宽度 .grid-container {display: grid;grid-template-columns: 80px 200px auto 40px; }.grid-container {display: grid;grid-template-columns: auto auto auto auto;//表示所有列的宽度…

Starrocks部署前期准备

前提条件 硬件要求 CPU StarRocks 依靠 AVX2 指令集充分发挥其矢量化能力。因此,在生产环境中,强烈建议您将 StarRocks 部署于 x86 架构 CPU 的服务器上。 您可以在终端中运行以下命令来检查 CPU 是否支持 AVX2 指令集: cat /proc/cpuin…

高效评优:基于SpringBoot的学生奖励管理系统

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理学生评奖评优管理系统的相关信息成为必然。…

全连接前馈网络:深度学习的基础架构解析

全连接前馈网络:深度学习的基础架构解析 全连接前馈网络,也称为多层感知机(MLP, Multi-Layer Perceptron),是深度学习中最基础的神经网络结构之一。这种网络由多个层次的神经元组成,每一层都完全连接到前一…

[JAVAEE] 线程安全问题

目录 一. 什么是线程安全 二. 线程安全问题产生的原因 三. 线程安全问题的解决 3.1 解决修改操作不是原子性的问题 > 加锁 a. 什么是锁 b. 没有加锁时 c. 加锁时 d. 死锁 e. 避免死锁 3.2 解决内存可见性的问题 > volatile关键字 (易变的, 善变的) a. 不加…

古埃及象形文字在线字典

我在个人网站“小孔的埃及学站点”上推出了在线的象形文字字典,总共收罗了将近700条的象形文字(词)。在线字典的使用方法很简单,在网站各大版块首页的右上方会有如下图所示的查询入口。 点击文本框,输入中文或英文关键…