当前位置: 首页 > news >正文

Unity官方文档中关于内存管理的翻译(2021.3)

原文:Memory in Unity - Unity 手册

Unity内存管理

为了确保您的应用程序运行时没有性能问题,了解Unity如何使用和分配内存非常重要。本文档的这一部分解释了Unity中内存是如何工作的,适用于希望了解如何提高应用程序内存性能的读者。

Unity使用三个内存管理层来处理应用程序中的内存:

1. 托管内存:一个受控的内存层,使用托管堆和垃圾收集器来自动分配和分配内存。

2. C#非托管内存:与Unity Collections命名空间和包一起使用的内存管理层。这种内存类型称为“非托管”,因为它不使用垃圾收集器来管理未使用的内存部分。

3. 本地内存:Unity用于运行引擎的C++内存。在大多数情况下,这个内存对Unity用户是不可访问的,但如果您想要微调应用程序性能的某些方面,了解它可能会有用。

托管内存

Mono和IL2CPP的脚本虚拟机(VM)实现了托管内存系统,有时也称为脚本内存系统。这些VM提供了一个受控内存环境,分为以下不同类型:

- 托管堆:VM自动控制的内存部分,使用垃圾收集器(GC)来管理。因此,分配在托管堆上的内存被称为GC分配。分配的任何发生都会在Profiler中记录为GC.Alloc样本。
- 脚本堆栈:当应用程序进入和退出任何代码范围时,堆栈会构建和解开。
- 本地VM内存:包含与Unity的脚本层相关的内存。在大多数情况下,您不需要操作本地VM内存,但了解它包括与代码生成相关的执行代码内存,尤其是关于泛型使用、Reflection使用的类型元数据以及运行VM所需的内存。

由于托管内存系统使用VM,它具有受控环境,自动跟踪分配的引用以管理其生命周期。这意味着您的应用程序不太可能在其他代码尝试访问内存时过早释放内存。这还意味着您对内存泄漏有一些保障,当内存从代码或未使用的内存堆积中不可访问时发生。

在Unity中使用托管内存是管理应用程序内存的最简单方法;但它也有一些缺点。垃圾收集器很方便使用,但在释放和分配内存时的方式不可预测,这可能会导致性能问题,比如当垃圾收集器必须停止释放和分配内存时会发生卡顿。为了解决这种不可预测性,您可以使用C#非托管内存层。

有关托管内存工作原理的更多信息,请参阅托管内存文档。

C#非托管内存

C#非托管内存层允许您访问本地内存层以微调内存分配,同时编写C#代码非常方便。

您可以使用Unity核心API中的Unity.Collections命名空间(包括NativeArray)以及Unity Collections包中的数据结构来访问C#非托管内存。如果您使用Unity的C#作业系统或Burst,您必须使用C#非托管内存。有关更多信息,请参阅作业系统和Burst的文档。

本地内存

Unity引擎的内部C/C++核心具有自己的内存管理系统,称为本地内存。在大多数

情况下,您不能直接访问或修改这种内存类型。

Unity将您项目中的场景、资产、图形API、图形驱动程序、子系统和插件缓冲区以及本地内存内的分配都存储在本地内存中,这意味着您可以通过Unity的C# API间接访问本地内存。这意味着您可以安全且轻松地操作应用程序的数据,而不会失去Unity本地核心中的本地和高性能代码的好处。

大多数情况下,您不需要与Unity的本地内存交互,但每当您使用Profiler时,都可以通过Profiler标记来查看它如何影响应用程序的性能。

原文:Managed memory - Unity 手册

Managed memory

Unity的托管内存系统是基于Mono或IL2CPP虚拟机(VMs)的C#脚本环境。托管内存系统的好处在于它管理内存的释放,因此您不需要通过代码手动请求释放内存。

Unity的托管内存系统使用垃圾回收器和托管堆来自动释放内存分配,当您的脚本不再持有对这些分配的引用时。这有助于防止内存泄漏。内存泄漏发生在分配了内存后,对它的引用丢失,然后永远不会释放内存,因为它需要引用才能释放。

这个内存管理系统还保护内存访问,这意味着您不能访问已被释放的内存,或者对于您的代码来说从未有效的内存。然而,这个内存管理过程会影响运行时性能,因为分配托管内存对CPU来说是耗时的。垃圾回收也可能会在完成之前阻止CPU执行其他工作。

值类型和引用类型

当调用一个方法时,脚本后端会将其参数的值复制到为该特定调用保留的内存区域中,这个数据结构称为调用堆栈。脚本后端可以快速复制占用几个字节的数据类型。然而,对象、字符串和数组通常要大得多,而且脚本后端定期复制这些类型的数据是低效的。

在托管代码中,所有非空引用类型对象和所有装箱的值类型对象都必须分配在托管堆上。

熟悉值类型和引用类型对于有效管理代码很重要。有关更多信息,请参阅Microsoft的有关值类型和引用类型的文档。

自动内存管理

当创建对象时,Unity会从称为堆的中央池中分配所需的内存,这是您的Unity项目选择的脚本运行时(Mono或IL2CPP)自动管理的内存部分。当对象不再使用时,曾经占用的内存可以被回收并用于其他用途。

Unity的脚本后端使用垃圾回收器来自动管理应用程序的内存,因此您不需要使用显式方法调用来分配和释放这些内存块。自动内存管理需要的编码工作较少,并减少了内存泄漏的可能性。

托管堆概述

托管堆是您的Unity项目选择的脚本运行时(Mono或IL2CPP)自动管理的内存部分。

在上面的图表中,蓝色框表示Unity分配给托管堆的一定数量的内存。其中的白色框代表Unity在托管堆的内存空间内存储的数据值。当需要额外的数据值时,Unity会从托管堆(标有A的地方)分配它们的空间。

内存碎片和堆扩展

上图显示了内存碎片的示例。当Unity释放一个对象时,该对象占用的内存会被释放。然而,空闲空间不会成为一个“自由内存”的单一大池。

已释放对象的两侧可能仍在使用。因此,被释放的空间是其他内存段之间的“间隙”。Unity只能使用这个间隙来存储与已释放对象相同或更小尺寸的数据。

这种情况被称为内存碎片化。当堆中有大量可用内存,但只能在对象之间的“间隙”中使用时,就会发生这种情况。这意味着即使总共有足够的空间来分配大块内存,托管堆也找不到足够大的连续内存块来分配给该分配。

(被标注为A的对象是需要添加到堆上的新对象。被标注为B的项目是已释放对象占用的内存空间,以及空闲的未分配内存。尽管总的空闲空间足够,但由于没有足够的连续空间,所以被标注为A的新对象的内存无法适应堆,因此必须运行垃圾收集器。)

如果分配了一个大对象,并且没有足够的连续空闲空间来容纳它,如上所示,Unity内存管理器会执行两个操作:

首先,如果垃圾回收器尚未运行,则运行垃圾回收器。这试图释放足够的空间来满足分配请求。

如果在垃圾回收器运行后,仍然没有足够的连续空间来容纳请求的内存量,则必须扩展堆。堆扩展的具体量取决于平台,但在大多数平台上,当堆扩展时,它会扩展到前一次扩展的两倍。

托管堆扩展注意事项

堆意外扩展可能会引发问题。Unity的垃圾收集策略倾向于更频繁地碎片化内存。您应该注意以下事项:

Unity不会在定期扩展堆时释放分配给托管堆的内存;相反,它会保留扩展的堆,即使其中的大部分部分为空。这是为了防止需要重新扩展堆,如果发生更多的大型分配。

在大多数平台上,Unity最终会将托管堆的空闲部分使用的内存释放回操作系统。这种情况发生的间隔不受保证,不可靠。

相关文章:

Unity官方文档中关于内存管理的翻译(2021.3)

原文:Memory in Unity - Unity 手册 Unity内存管理 为了确保您的应用程序运行时没有性能问题,了解Unity如何使用和分配内存非常重要。本文档的这一部分解释了Unity中内存是如何工作的,适用于希望了解如何提高应用程序内存性能的读者。 Unity使用三个内…...

点云处理开发测试题目 完整解决方案

点云处理开发测试题目 文件夹中有一个场景的三块点云数据,单位mm。是一个桌子上放了一个纸箱,纸箱上有四个圆孔。需要做的内容是: 1. 绘制出最小外接立方体,得到纸箱的长宽高值。注意高度计算是纸箱平面到桌子平面的距离。 2. 计算出纸箱上的四个圆的圆心坐标和半径,对圆…...

TensorRT的结构

Builder(网络原数据):模型搭建的入口,网络的tensorRT内部表示以及可执行程序引擎都是由该对象的成员方法生成的 BuiderConfig(网络原数据的选项):负责设置模型的一些参数,如是否开始…...

python对excel数据表进行数据清洗

当拿到excel表,使用python对excel操作前,第一件事情是对excel表的数据进行数据清洗。 数值是否有空值,是否有重复的数据,把以上2个问题解决完成以后,才是对数据真正操作的开始。 1、使用pandans读取数据 2、判断exce…...

95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询

Spring Data Redis 之使用RedisTemplate 实现自定义查询 Book实体类 原本的接口,再继承我们自定义的接口 自定义查询接口----CustomBookDao 实现类:CustomBookDaoImpl 1、自定义添加hash对象的方法 2、自定义查询价格高于某个点的Book对象 测试&a…...

jdbc(DriverManager+Connection+Statement+ResultSet)+SQL注入+开启预编译+数据连接池

1 JDBC概念 JDBC 就是使用Java连接并操作数据库的一套API 全称:( Java DataBase Connectivity ) Java 数据库连接 2 JDBC优势 可随时替换底层数据库,访问数据库的Java代码基本不变 以后编写操作数据库的代码只需要面向JDBC(接口&#xf…...

NoSQL之 Redis命令工具及常用命令

目录 1 Redis 命令工具 1.1 redis-cli 命令行工具 1.2 redis-benchmark 测试工具 2 Redis 数据库常用命令 2.1 set:存放数据,命令格式为 set key value 2.2 get:获取数据,命令格式为 get key 2.3 keys 命令可以取符合规则的…...

多线程(线程互斥)

抢票代码编写 学习了前面有关线程库的操作后,我们就可以模拟抢票的过程 假设我们创建四个线程,分别代表我们的用户 然后设定总票数为1000张,四个线程分别将进行循环抢票操作,其实就是循环对票数进行打印,并进行对应的…...

使用 html2canvas 和 jspdf 将页面转 pdf,同时解决当页面过长时,页面白屏问题

代码如下,直接粘贴复制即可,代码中 jspdf 是全局引入,你可以自己局部引入 别人使用标签的方式来显示 base64,但是当页面过长时,base64 大小过大会导致页面解析异常,显示白屏 import html2canvas from html2…...

【Python 千题 —— 基础篇】今年几岁啦

题目描述 题目描述 介绍自己的年龄。请使用 input 函数读入一个整数,表示自己的年龄,然后程序将自动生成介绍自己年龄的英文语句。 输入描述 输入一个整数,表示自己的年龄。 输出描述 程序将生成一个英文语句,以介绍自己的年…...

git push 失败 shallow update not allowed

问题描述: ~/OK62xx-linux-sdk/OK62xx-linux-kernel$ git push origin master Counting objects: 83919, done. Delta compression using up to 144 threads. Compressing objects: 100% (75697/75697), done. Writing objects: 100% (83919/83919), 232.41 MiB | …...

uniapp 在uni.scss 根据@mixin定义方法 、通过@include全局使用

在官方文档中提及到uni.scss中变量的使用,而我想定义方法,这样写css样式更方便 一、官方文档的介绍 根据官方文档我知道,在这面定义的变量全局都可使用。接下来我要在这里定义方法。 二、在uni.scss文件中定义方法 我在uni.scss文件中定义了…...

C++ 类和对象(一)

1.面向过程和面向对象初步认识 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 C是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完 成。 …...

rust函数

一 、函数定义 (一)格式 使用fn关键字 fn是 function 的缩写 1.无返回值的 fn 函数名 ( [paraname: type]... ) {函数体 }参数必须声明参数名称和类型 函数定义时指定的参数叫做 形参。调用时传递给函数的参数叫做 实参。 例子 fn another_function(…...

链表的基本操作

(一)实验类型:设计性 (二)实验目的: 1. 掌握线性表的链式存贮结构及基本操作,深入了解链表的基本特性,以便在实际问题背景下灵活运用它们。 2. 巩固该存贮结构的构造方法&#xff0…...

Flutter AI五子棋

前言 在上一篇文章中,讲解了如何实现双人在本地对战的五子棋,但是只有一个人的时候就不太好玩,同时博主也没有把五子棋相关的文章写过瘾。那么这篇文章,我们来实现一个功能更加丰富的五子棋吧!在设计五子棋的算法方面&…...

springboot项目中后台文件上传处理

参考地址:http://www.gxcode.top/code 文件上次核心处理代码: @Autowired private FileUpload fileUpload; //获取资源对象:file-upload-prod.properties@ApiOperation(value = "用户头像修改", notes = "用户头像修改", httpMethod =...

【SQL】MySQL中的存储引擎、事务、锁、日志

存储引擎: 数据库管理系统(DBMS)使用数据存储引擎进行创建、查询、更新和删除数据。 MySQL5.5之前默认的存储引擎是MyISAM,5.5及之后版本默认的存储引擎是InnoDB。(my.ini中指定的) MyISAM:不支持事务,不支…...

DRM全解析 —— CRTC详解(2)

接前一篇文章:DRM全解析 —— CRTC详解(1) 本文继续对DRM中CRTC的核心结构struct drm_crtc的成员进行释义。 3. drm_crtc结构释义 (5)struct drm_modeset_lock mutex /*** @mutex:** This provides a read lock for the overall CRTC state (mode, dpms* state, ...) an…...

3d环形图开发(vue3+vite+ts)

开发效果&#xff08;待完善&#xff09;&#xff1a; 技术支持&#xff1a; Echarts echarts-gl 安装&#xff1a; 注&#xff1a;echarts与echarts-gl版本需对应&#xff0c;可参考官网 pnpm add echarts4.9.0 echarts-gl1.1.2 组件封装&#xff1a; <template><…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...