https://blog.uwa4d.com/archives/presentandsync.html

WaitForTargetFPS、Gfx.WaitForPresent 和 Graphics.PresentAndSync是我们经常会被问到的参数。想必正在读此文的你也经常在Profiler中遇到过这几项CPU开销过大的情况。对此,我们今天就来好好地聊一聊这几个参数的具体含义和触发规则。


WaitForTargetFPS

该参数一般出现在CPU开销过低,且通过设定了目标帧率的情况下(Application.targetFrameRate)。当上一帧低于目标帧率时,将会在本帧产生一个WaitForTargetFPS的空闲等待耗时,以维持目标帧率。

解析:该项在Unity引擎的主循环中其实是最早执行的,即引擎实际上是根据上一帧的CPU耗时,在当前帧中通过增补WaitForTargetFPS的方式来将运行FPS维持到目标值。比如,目标帧率为30帧/秒,上一帧耗时15ms,那么当前帧中WaitForTargetFPS将会是18(33-15)ms,但是这一帧中其他耗时为28ms,那么在Profiler中这一帧的总耗时就变成了46(18+28)ms。

因此,由该值造成了Profiler开销较高的现象,其实是耗时的“假象”,在优化过程中,你对它可以“视而不见”。

Gfx.WaitForPresent && Graphics.PresentAndSync

这两个参数在Profiler中经常出现CPU占用较高的情况,且仅在发布版本中可以看到。究其原因,其实是CPU和GPU之间的垂直同步(VSync)导致的,之所以会有两种参数,主要是与项目是否开启多线程渲染有关。当项目开启多线程渲染时,你看到的则是Gfx.WaitForPresent;当项目未开启多线程渲染时,看到的则是Graphics.PresentAndSync

Graphics.PresentAndSync 是指主线程进行Present时的等待时间和等待垂直同步的时间。Gfx.WaitForPresent其字面意思同样也是进行Present时需要等待的时间,但这里其实省略了很多的内容。其真实的意思应该是为了在渲染子线程(Rendering Thread)中进行Present,当前主线程(MainThread)需要等待的时间。听起来依然很拗口,下面,我们就来进行详细地解释。

当项目开启多线程程渲染时,引擎会将Present等相关工作尽可能放到渲染线程去执行,即主线程只需通过指令调用渲染线程,并让其进行Present,从而来降低主线程的压力。但是,当CPU希望进行Present操作时,其需要等待GPU完成上一次的渲染。如果GPU渲染开销很大,则CPU的Present操作将一直处于等待操作,其等待时间,即为当前帧的Gfx.WaitForPresent时间,如下图所示。

同理,当项目未开启多线程渲染时,引擎会在主线程中进行Present(当前绝大多数的移动游戏均在使用该中操作),当然,Present操作同样需要等待GPU完成上一次的渲染。如果GPU渲染开销很大,则CPU的Present操作将一直处于等待操作,其等待时间,即为当前帧的Graphics.PresentAndSync时间,如下图所示。

我们做了一个较为极端的例子来展示这种情况。在Unity 5.3.3版本上,创建60个全屏UIPanel,分别开启和关闭多线程渲染,并不设置TargetFPS。那么,在三星S6设备上该参数的CPU开销如下:

开启多线程渲染时:

关闭多线程渲染时:

所以,如果你的项目中,Gfx.WaitForPresent或Graphics.PresentAndSync的CPU耗时非常高时,其实并不是它们自己做了什么神秘的操作,而是你当前的渲染任务太重,GPU负载过高所致

同时,对于开启垂直同步的项目而言,Gfx.WaitForPresent 和 Graphics.PresentAndSync也会出现CPU占用较高的情况。在解释这种问题之前,我们先以“大家乘坐地铁”来举个例子。一般来说,地铁到达每一站的时间均是平均且一定的,假设每10分钟一班接走一批乘客。但是几乎没有多少乘客可以按点到达,如果提前两分钟到达,则只需要等待两分钟即可乘上地铁,但是,如果你错过了,哪怕只差了一分钟,那么你也不得不再等待九分钟才能乘上地铁。

上述的情况我们经常会遇到。在GPU的渲染流水线中,其转换front buffer和back buffer的工作原理和“乘坐地铁”其实是一致的。大家可以把GPU的流水线简单地想象成为一列地铁。对于移动设备来说,GPU的帧率一般为30帧/秒或60帧/秒,即VSync每33ms或每16.6ms“到站一次”,CPU的Present即为“乘客乘上地铁”,然后前往各自的目的地。与乘客的早到和晚到一样,CPU的Present也会出现类似的情况,比如:

CPU端开销非常小,Present在很早即被执行,但此时VSync还没到,则会出现较高的等待时间,即Gfx.WaitForPresent 和 Graphics.PresentAndSync的CPU开销看上去很高。下图为Unity 5.3.3版本上,一个空场景在不开启多线程渲染、不设置TargetFPS的情况下,Graphics.PresentAndSync在三星S6设备上的CPU占用情况。

CPU端开销很高,使得Present执行时错过了VSync操作,这样,Present将不得不等待下一次VSync的到来,从而造成了Gfx.WaitForPresent 和 Graphics.PresentAndSync的CPU开销较高。这种情况在CPU端加载过量资源时特别容易发生,比如WWW加载较大的AssetBundle、Resource.Load加载大量的Texture等等。

通过以上的讲解,我们希望此刻的你已经对Gfx.WaitForPresent 和 Graphics.PresentAndSync已经有了深入的理解。这两个参数无论CPU占用多少,其实都不是这两个参数的自身问题,而是项目的其他部分造成。对此,我们做一个总结,以方便你进一步加深印象。

造成这两个参数的CPU占用较高的原因主要有以下三种原因:

CPU开销非常低,所以CPU在等待GPU完成渲染工作或等待VSync的到来;
CPU开销很高,使Present错过了当前帧的VSync,即不得不等待下一次VSync的到来;
GPU开销很高,CPU的Present需要等待GPU上一帧渲染工作的完成。

最后,如何优化并降低这两个参数的CPU占用呢? 那就是,忽略Gfx.WaitForPresent 和 Graphics.PresentAndSync这两个参数,优化其他你能优化的一切

转载:扒一扒Profiler中这几个“占坑鬼”的更多相关文章

  1. Vue中的slot(占坑,预留位置)

    Vue中的slot(占坑,预留位置) 子模板不使用slot 子模板使用slot 子模板使用使用name属性,且传递data 文件名:Slots.vue //slot组件 <template> ...

  2. 【转载】Callable、FutureTask中阻塞超时返回的坑点

    本文转载自:http://www.cnblogs.com/starcrm/p/5010863.html 案例1: package com.net.thread.future; import java. ...

  3. linux2.6.24内核源代码分析(2)——扒一扒网络数据包在链路层的流向路径之一

    在2.6.24内核中链路层接收网络数据包出现了两种方法,第一种是传统方法,利用中断来接收网络数据包,适用于低速设备:第二种是New Api(简称NAPI)方法,利用了中断+轮询的方法来接收网络数据包, ...

  4. linux2.6.24内核源代码分析(1)——扒一扒sk_buff

    最近研究了linux内核的网络子系统上的网络分组的接收与发送的流程,发现这个叫sk_buff的东西无处不在,内核利用了这个结构来管理分组,在各个层中传递这个结构,因此sk_buff可以说是linux内 ...

  5. View绘制详解(三),扒一扒View的测量过程

    所有东西都是难者不会,会者不难,Android开发中有很多小伙伴觉得自定义View和事件分发或者Binder机制等是难点,其实不然,如果静下心来花点时间把这几个技术点都研究一遍,你会发现其实这些东西都 ...

  6. 扒一扒ReentrantLock以及AQS实现原理

    提到JAVA加锁,我们通常会想到synchronized关键字或者是Java Concurrent Util(后面简称JCU)包下面的Lock,今天就来扒一扒Lock是如何实现的,比如我们可以先提出一 ...

  7. 扒一扒.NET Core的环境配置提供程序

    很久之前,在玩Docker的时候顺便扒了扒,最近,终于下定决心花了些时间整理并成文,希望能够给大家一些帮助. 目录 .NET Core中的配置 ASP.NET Core中的配置 扒一扒环境变量提供程序 ...

  8. 扒一扒EOS的前世今生

    扒一扒EOS的前世今生 EOS是什么?   EOS可以认为是Enterprise Operation System的缩写,即商用的一款分布式区块链操作系统,EOS主要为了解决百万级用户的使用问题,为企 ...

  9. ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案 try.dot.net 的正确使用姿势 .Net NPOI 根据excel模板导出excel、直接生成excel .Net NPOI 上传excel文件、提交后台获取excel里的数据

    ASP.NET Core 2.2 : 十六.扒一扒新的Endpoint路由方案   ASP.NET Core 从2.2版本开始,采用了一个新的名为Endpoint的路由方案,与原来的方案在使用上差别不 ...

随机推荐

  1. Cracking The Coding Interview3.3

    //Imagine a (literal) stack of plates. If the stack gets too high, it might topple. Therefore, in re ...

  2. 异步设备IO OVERLAPPED结构(设备内核对象 事件内核对象 可提醒IO)

    同步IO是指:线程在发起IO请求后会被挂起,IO完成后继续执行. 异步IO是指:线程发起IO请求后并不会挂起而是继续执行.IO完毕后会得到设备驱动程序的通知. 一.异步准备与OVERLAPPED结构 ...

  3. let var区别

    function varTest() { var x = 1; if (true) { var x = 2; // 同样的变量! console.log(x); } console.log(x); } ...

  4. fabric运维

    fabric中文文档:http://fabric-chs.readthedocs.io/zh_CN/chs/ 视频教程:http://study.163.com/course/courseMain.h ...

  5. 2010年腾讯前端面试题学习(js部分)

    看了牛人写的回忆文章,里面有2010年腾讯的前端面试题,里面涉及到不少基础性的问题,学习一下:) 原文地址:https://segmentfault.com/a/1190000012998107 js ...

  6. Delphi 10.3终于来了

    http://altd.embarcadero.com/download/radstudio/10.3/delphicbuilder10_3_0_94364.iso   安装工具: http://ww ...

  7. 1.Windows下使用VisualSVN Server搭建SVN服务器

    使用 VisualSVN Server来实现主要的 SVN功能则要比使用原始的 SVN和Apache相配合来实现源代码的 SVN管理简单的多,下面就看看详细的说明. VisualSVN Server的 ...

  8. 如何在VMware中安装Linux系统

    这篇文章主要讲述如何在VMware12中安装RHEL6.9Linux操作系统 步骤一: 打开VMware软件,在主页中点击创建新的虚拟机或者点击左上角文件,在列表中点击新建虚拟机,如图: 步骤二: 点 ...

  9. 1.4 Chrome浏览器

    1.4 Chrome浏览器 前言selenium2启动Chrome浏览器是需要安装驱动包的,但是不同的Chrome浏览器版本号,对应的驱动文件版本号又不一样,如果版本号不匹配,是没法启动起来的. ## ...

  10. NSCTF2015 逆向第五题分析

    这道题目我没有写出Exploit,因为编码时候里面几个细节处理出错.但对程序的逆向分析已完成,这里就学习一下别人写Exploit的思路.主要参考:绿盟科技网络攻防赛资料下载 0x01 题目要求 题目要 ...