unity性能分析

以下为 Unity 分析器使用的端口:

	多播端口 (MulticastPort): 54998
	侦听端口 (ListenPorts): 55000 - 55511
	多播(单元测试): 55512 - 56023

您应在网络节点内访问这些端口。也就是说,在 Unity 编辑器 (Editor) 上开启分析器 (Profiler) 时,您正尝试分析的设备应看到机器上的这些端口。

第一步

Unity 在处理蒙皮、批处理、物理、用户脚本、粒子等方面依赖于 CPU (对其中的 SIMD 部分(如 x86 上的 SSE 或 ARM 上的 NEON)进行高度优化)。

GPU 用于处理着色器、绘制调用和图像效果。

CPU 或 GPU 绑定

  • 使用内部分析器检测 CPU 和 GPU ms

帕累托分析

大多数问题 (80%) 是由几个关键原因 (20%) 引起的。

  1. 使用编辑器 (Editor) 分析器获取大部分有问题的函数调用并首先将其优化。
  2. 确保只在必要时运行脚本。
    1. 使用 OnBecameVisible/OnBecameInvisible 禁用不活跃对象。
    2. 如果您无需使用一些脚本来运行每一帧,请使用协同程序。

    // Do some stuff every frame:
    void Update () {
    }
    
    //Do some stuff every 0.2 seconds:
    IEnumerator Start ()_ {
    while (true) {
    yield return new WaitForSeconds (0.2f);
       }
    }

  1. 使用 .NET System.Threading.Thread 类将繁琐的计算放入其它线程。这允许您在多个内核上运行,但 Unity API 并不能保证线程安全。因此,缓冲区将在主线程上对其进行输入、输出、读取和赋值。

CPU 性能分析

用户代码分析

并非所有用户代码都会显示在分析器 (Profiler) 中。但是,您可使用 Profiler.BeginSampleProfiler.EndSample 让分析器显示所需的用户代码。

GPU 性能分析

Unity 编辑器 (Editor) 分析器目前无法显示 GPU 数据。我们正与硬件制造商合作,让其与 Tegra 设备一起首先显示在编辑器 (Editor) 分析器中。

iOS

iOS 工具

  • Unity 内部分析器(不是编辑器 (Editor) 分析器)。这显示了整个场景的 GPU 时间。
  • PowerVR PVRUniSCo 着色器分析器。见下文。
  • iOS:Xcode OpenGL ES 驱动程序工具 (Driver Instruments) 仅显示高层次信息:
    • 设备利用率% - 渲染占用的总 GPU 时间。

>95% 意味着此应用程序与 GPU 绑定在一起。

  • 渲染器利用率 % - 绘制像素所占用的 GPU 时间。
  • 平铺器利用率 % - 处理顶点所占用的 GPU 时间。
  • 分裂计数 - 顶点数据与分配的缓冲区不符时,帧分裂的次数。

PowerVR 是基于平铺的延时渲染器,因此无法获取每次绘制调用的 GPU 计时。但是,您可以使用 Unity 内置分析器(将结果打印到 Xcode 输出的分析器)来获取整个场景的 GPU 时间。目前,苹果工具只能告诉您 GPU 及其部件的繁忙程度,不能为您提供 精确到毫秒的时间报告。

PVRUniSCo 提供 了整个着色器的周期及该着色器代码中每一行的 近似周期。Windows 与 Mac!但无论如何,它将不能与苹果驱动程序正在执行的任务完全匹配。尽管如此,它仍不失为一个不错的变通方案。

Android

Android 工具

  • Adreno (Qualcomm)
  • NVPerfHUD (NVIDIA)
  • PVRTune, PVRUniSCo (PowerVR)

在 Tegra 中,NVIDIA 提供 的工具可以在 Windows、OSX 和 Linux 的系统上运行,性能卓越,能满足您的各种需求,如每次绘制调用的 GPU 时间、每个着色器的周期、强制 2x2 纹理以及空视图矩形。PerfHUD ES 很难与消费者设备兼容,此时您需要使用 NVIDIA 开发板。

Qualcomm 提供 了性能卓越的 Adreno Profiler (仅在 Windows 上使用),虽然它只能在 Windows 上使用,但能与消费者设备兼容!它具备时间轴 (Timeline) 图形、帧捕获、帧调试、API 调用、着色器 (Shader) 分析器和实时编辑等功能。

与图形相关的CPU性能分析

内部分析器很好地概括了每个模块:

  • OpenGL ES API 占用的时间
  • 批处理效率
  • 蒙皮、动画、粒子

内存

其中包含 Unity 内存和 mono 内存。

Mono 内存

Mono 内存为 Unity 对象(游戏对象、资源、组件等)处理脚本对象和包装。当资源分配与可用内存不匹配或位于 System.GC.Collect() 调用上时,垃圾回收器 (Garbage Collector) 将清理空间。

内存位于堆块中。如果内存无法将数据装入分配的块,则可分配更多的块。应用程序关闭前,堆块保存在 Mono 中。换句话说,Mono 不会释放任何用于 OS (Unity 3.x) 的内存空间。一旦您分配了一定量的内存,系统将为 mono 预留内存,并且不能供 OS 使用。 甚至当你释放内存时,它将只供在 Mono 内部使用,不会供 OS 使用。分析器 (Profiler) 中的堆内存值只会增加,从不会降低。

如果系统不能将新数据装入分配的堆块中,Mono 会调用一个 "GC" 并分配一个新的堆块(如,由于碎片的原因)。

太多的堆节 意味着 Mono 内存已用完(由碎片或大量使用内存导致)。

使用 System.GC.GetTotalMemory 获取使用的总 Mono 内存。

通常,我们建议您使用尽可能小的分配。

Unity 内存

Unity 内存可处理资源 (Asset) 数据(纹理 (Textures)、网格 (Meshes)、音频 (Audio)、动画 (Animation) 等)、游戏对象 (Game object) 和内置引擎 (Engine)(渲染 (Rendering)、粒子 (Particles)、物理 (Physics) 等)。使用 Profiler.usedHeapSize 获取使用的总 Unity 内存。

内存映射

目前还没有任何工具,但您可使用以下方法。

  • Unity 分析器 – 不完美的阶段性产品,但大致了解其功能会对您有所裨益。其可在此设备上运行!
  • 内部分析器
    • 显示用过的堆和分配的堆 – 参见 mono 内存。
    • 显示每帧中 mono 分配的次数。
  • Xcode 工具 - iOS
    • Xcode 工具活动监视器 (Instruments Activity Monitor) – 实际内存 (Real Memory) 空间柱形图。
    • Xcode 工具分配 (Instruments Allocations) – 所创建对象与活跃对象的净分配。
    • VM 追踪器 (Tracker)
      • 通常,纹理分配有 IOKit 标签。
      • 网格通常存入 VM 分配 (Allocate) 中。
  • 制作自己的工具
    • FindObjectsOfTypeAll (type :Type) :Object[]
    • FindObjectsOfType (type :Type):Object[]
    • GetRuntimeMemorySize (o :Object) :int
    • GetMonoHeapSize
    • GetMonoUsedSize
    • Profiler.BeginSample/EndSample – 分析自己的代码
    • UnloadUnusedAssets () :AsyncOperation
    • System.GC.GetTotalMemory/Profiler.usedHeapSize
  • 下载对象参考文件 – 无法找到它。一个变通方案是为公共变量 找出场景参考文献。

内存中断

  • 垃圾回收器
    • 系统不能将新数据装入分配的堆块中时,它就会开始工作。
    • 请勿在移动设备上使用 OnGUI
      • 它会在每帧上调用数次
      • 它会重新绘制此视图。
      • 它创建了大量的内存分配调用,这需要调用垃圾回收 (Garbage Collection)。
    • 过于迅速地创建/移除太多对象?
      • 这可能导致碎片产生。
      • 使用编辑器 (Editor) 分析器追踪内存活动。
      • 内部分析器可追踪 mono 内存活动。
    • System.GC.Collect() 出现中断,您可以使用此.Net 函数。
  • 新内存分配
    • 分配中断
      • 使用预先分配的可复用类实例列表实施自己的内存管理方案。
      • 切勿向每帧分配过大空间,而要对其进行缓存并预先分配
    • 碎片问题?
      • 预先分配内存池。
      • 保存一份不活跃游戏对象 (GameObjects) 的清单,重复使用它们,而不要将其实例化 (Instantiating) 和销毁 (Destroying)。
    • mono 内存耗尽
      • 分析内存活动 – 第一个内存页面什么时候填满?
      • 您真的需要这么多游戏对象吗?单个内存页面不够用?
    • 对于本地数据,请使用结构体而非类。类存储在堆中;结构体存储在堆栈中。

    class MyClass {
    public int a, b, c;
    }
    
    struct MyStruct {
    public int a, b, c;
    }
    
    void Update () {
    //BAD
    // allocated on the heap, will be garbage collected later!
    MyClass c = new MyClass();
    
    //GOOD
    //allocated on the stack, no GC going to happen!
    MyStruct s = new MyStruct();
    }

内存不足崩溃

虽然在理论上游戏应该能够良好运行,但有些时候,游戏可能会因“内存不足”而崩溃。出现此问题时,请比较您的常规游戏内存占用情况和崩溃时分配的内存空间大小。如果数值相差很远,则存在一个内存峰值。潜在的原因包括:

  • 同时加载了两个大的场景 – 在两个较大的场景之间使用一个空场景来修复此问题。
  • 加载附加场景 – 清除无用部分,维护内存空间大小。
  • 将巨大的资源包加载至内存
  • 通过 WWW 或(大量的)大对象的实例化来加载,例如:
    • 未进行适当压缩的纹理(不适用于移动设备)。
    • 启用获取/设置 (Get/Set) 像素的纹理。这需要使用一份内存中未压缩的纹理副本。
  • 运行时基本上不会解压从 JPEG/PNG 加载的纹理。
    • 将大 mp3 文件标记为加载时解压缩。
  • 在静态 monobehavior 字段等异常缓存中保存不用的资源,这将导致变更场景时,不会清理内存。
原文地址:http://docs.manew.com/Manual/MobileProfiling.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值