22.Profiler窗口脚本控制

22.Unity性能分析工具-Profiler窗口脚本控制


22.1 知识点

Profiler提供的重要API

使用以下 API 前需引用命名空间:using UnityEngine.Profiling;

Mono托管堆(C#层内存)

  1. Profiler.GetMonoUsedSizeLong()
    获取当前使用的 Mono 堆内存(单位:字节),用于关注脚本(C#)对象占用的内存。
    示例:print("当前使用的Mono堆内存:" + Profiler.GetMonoUsedSizeLong());

  2. Profiler.GetMonoHeapSizeLong()
    获取 Mono 堆的总大小,用来判断 Mono 内存是否接近上限。
    示例:print("Mono堆的总大小:" + Profiler.GetMonoHeapSizeLong());
    正常情况应满足:GetMonoUsedSizeLong() <= GetMonoHeapSizeLong()

  3. Profiler.usedHeapSizeLong
    当前堆中使用的内存总量,包括所有托管内存。表示 C# GC 堆当前被使用的内存(与 GetMonoUsedSizeLong 类似,但更底层),在某些平台下更准确。
    示例:print("当前堆中使用的内存总量;包括所有托管内存" + Profiler.usedHeapSizeLong);

Unity 总体内存情况

  1. Profiler.GetTotalAllocatedMemoryLong()
    获取所有 Unity 正在使用的内存总量(包括 Mono、Native、图形资源等),常用于分析整体内存走势。
    示例:long totalMemory = Profiler.GetTotalAllocatedMemoryLong();

  2. Profiler.GetTotalReservedMemoryLong()
    返回 Unity 从操作系统申请的内存总量,不管是否已经用上。包含:当前使用中的内存(已分配)、尚未使用但已预留的空间(为减少频繁申请)。

  3. Profiler.GetTotalUnusedReservedMemoryLong()
    返回 Unity 保留了但尚未分配出去的内存部分,即「空闲缓存池」。

三者关系:
正在使用中的内存总量 + 保留了但尚未分配出去的内存部分Unity 从操作系统申请的内存总量
即:GetTotalAllocatedMemoryLong() + GetTotalUnusedReservedMemoryLong() ≈ GetTotalReservedMemoryLong()

针对某个对象分析内存

  1. Profiler.GetRuntimeMemorySizeLong(object)
    获取某个对象占用的内存(估算值),包括纹理、网格等对象的实际内存占用。
    示例:Profiler.GetRuntimeMemorySizeLong(obj);(obj 可为 GameObject 等 Unity 对象)。

特定分析部分逻辑

  1. Profiler.BeginSample / Profiler.EndSample
    开始/结束一个自定义采样区段,常用于标记性能热点段,二者需成对使用。
    该区段会在 Unity Profiler 的 CPU 模块中显示为一条标记,建议仅在开发环境使用,可通过 #if UNITY_EDITOR 包裹避免构建时存在。
    用法:在要分析的逻辑前写 Profiler.BeginSample("标记名");,逻辑后写 Profiler.EndSample();

获取记录详细数据

  1. Profiler.logFile、Profiler.enableBinaryLog
    可将 Profiler 数据写入文件,用于离线分析(例如上传给 QA 或分析工具)。即在运行时手动采集 Unity Profiler 的原始性能数据(.raw 文件),这些数据可以导入 Unity Profiler 界面中进行离线分析。
    一般可在游戏中嵌入一个开启功能,采集一定时间的性能数据,再通过代码上传采样数据到服务器。
    示例流程:设置 Profiler.logFile = Application.persistentDataPath + "/myProfileData.raw"Profiler.enableBinaryLog = true 开始记录,采集若干秒后设为 false 停止记录。

更多Profiler API

更完整的接口说明见官方文档:
https://docs.unity3d.com/cn/2022.3/ScriptReference/Profiling.Profiler.html


22.2 知识点代码

Lesson22_Unity性能分析工具_Profiler窗口_脚本控制.cs

using UnityEngine;
using UnityEngine.Profiling;

public class Lesson22_Unity性能分析工具_Profiler窗口_脚本控制 : MonoBehaviour
{
    void Start()
    {
        #region 知识点一 Profiler提供的重要API

        /* 需要引用命名空间 using UnityEngine.Profiling; */

        #region Mono托管堆(C#层内存)

        /* 1. 获取当前使用的 Mono 堆内存(单位:字节);关注脚本(C#)对象占用的内存 */
        print("当前使用的Mono堆内存:" + Profiler.GetMonoUsedSizeLong());

        /* 2. 获取 Mono 堆的总大小;用来判断 Mono 内存是否接近上限 */
        print("Mono堆的总大小:" + Profiler.GetMonoHeapSizeLong());

        /* 正常来说 GetMonoUsedSizeLong() <= GetMonoHeapSizeLong() */

        /* 3. 当前堆中使用的内存总量,包括所有托管内存;
         *    C# GC 堆当前被使用的内存(与 GetMonoUsedSizeLong 类似,但更底层),在某些平台下更准确。 */
        print("当前堆中使用的内存总量;包括所有托管内存" + Profiler.usedHeapSizeLong);

        #endregion

        #region Unity 总体内存情况

        /* 4. 获取所有 Unity 正在使用的内存总量(包括 Mono、Native、图形资源等);常用于分析整体内存走势 */
        long totalMemory = Profiler.GetTotalAllocatedMemoryLong();
        print("Unity 正在使用的内存总量:" + totalMemory);

        /* 5. 返回 Unity 从操作系统申请的内存总量,不管是否已经用上;
         *    包含:当前使用中的内存(已分配)、尚未使用但已预留的空间(为减少频繁申请) */
        print("Unity 从操作系统申请的内存总量:" + Profiler.GetTotalReservedMemoryLong());

        /* 6. 返回 Unity 保留了但尚未分配出去的内存部分,即“空闲缓存池” */
        print("Unity 保留了但尚未分配出去的内存部分:" + Profiler.GetTotalUnusedReservedMemoryLong());

        /* 正在使用中的内存总量 + 保留了但尚未分配出去的内存部分 ≈ Unity 从操作系统申请的内存总量
         * GetTotalAllocatedMemoryLong() + GetTotalUnusedReservedMemoryLong() ≈ GetTotalReservedMemoryLong() */

        #endregion

        #region 针对某个对象分析内存

        /* 7. 获取某个对象占用的内存(估算值);包括纹理、网格等对象的实际内存占用 */
        GameObject obj = new GameObject();
        Profiler.GetRuntimeMemorySizeLong(obj);

        #endregion

        #region 特定分析部分逻辑

        /* 8. 开始一个自定义采样区段;常用于标记性能热点段,配合 EndSample() 使用。
         *    会在 Unity Profiler 的 CPU 模块中显示为一条标记,建议仅在开发环境使用。
         *    可通过 #if UNITY_EDITOR 包裹避免构建时存在。 */
        Profiler.BeginSample("MrTaoCode");

        /* 做一些逻辑或渲染操作 */
        for (int i = 0; i < 99999; i++)
        {
            float x = Mathf.Sqrt(i);
        }

        /* 结束采样区段 */
        Profiler.EndSample();

        #endregion

        #region 获取记录详细数据

        /* 9. 可将 Profiler 数据写入文件,用于离线分析(比如上传给 QA 或分析工具)。
         *    在运行时手动采集 Unity Profiler 的原始性能数据(.raw 文件),可导入 Profiler 界面中离线分析。
         *    一般可在游戏中嵌入开启功能,采集一定时间的性能数据,再主动上传采样数据到服务器。 */
        Profiler.logFile = Application.persistentDataPath + "/myProfileData.raw";
        Profiler.enableBinaryLog = true;  /* 开始记录 */
        /* yield return new WaitForSeconds(10f); */
        Profiler.enableBinaryLog = false; /* 停止记录 */

        #endregion

        #endregion

        #region 知识点二 更多Profiler API

        /* https://docs.unity3d.com/cn/2022.3/ScriptReference/Profiling.Profiler.html */

        #endregion
    }

    void Update()
    {
        Profiler.BeginSample("MrTaoCode");
        /* 做一些逻辑或渲染操作 */
        for (int i = 0; i < 99999; i++)
        {
            float x = Mathf.Sqrt(i);
        }
        /* 结束采样区段 */
        Profiler.EndSample();
    }
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏