渲染框架时,我的C#应用​​程序中出现了意外的峰值。我在探查器中进行了遍历,发现以下内容:

  • 打开vsync时,该程序似乎在交换缓冲区时将控制权交给了OS(或执行了某些操作)...并且在某种程度上保持了渲染的一致性。这很好,因为它可以平滑地渲染帧,并且没有怪异的微笔画。下图显示了被认为是完美的流体。这就是我们的情况,“它可以流畅地渲染而不会出现卡顿现象,从而完美地工作”。

  • c# - C#性能分析器显示了长时间的暂停,无法从提供的数据中确定它是什么-LMLPHP
  • 当vsync关闭并且该程序不执行任何操作,只是尽可能快地进行写入而没有任何中断,即使每秒的帧数更高,似乎也有很大的差距,无所事事。我很确定这是我在游戏中注意到的微结点,因为它将导致FPS急剧下降到60fps以下。下图显示了出问题的地方:

  • c# - C#性能分析器显示了长时间的暂停,无法从提供的数据中确定它是什么-LMLPHP

    在上面,增量时间为21毫秒(每秒60帧超过了16.6毫秒),并在游戏中造成明显的停顿。甚至比这还糟,因为它仅在它之后才开始渲染(如您之后的实心矩形所示),所以这21ms是一个谎言,根据该图,它更像是40ms,这太可怕了。

    当我不了解的原因打开vsync时,这种巨大的差距永远不会发生。对于不熟悉vsync和游戏的用户,您不能在第一人称射击游戏中使用vsync,因为由于其工作原理,它会削弱输入处理,因此我无法使用vsync,并且必须研究非vsync版本。我需要找到为什么非vsync版本具有这些主要停滞点的原因。

    我的问题是,如何确定您从以上图像中看到的这种延迟?

    性能分析器表示,这里有大量等待时间,超过80%的等待时间需要20%的CPU使用率(相比之下,准备渲染数据时需要100%的CPU使用率)。

    探查器还显示该循环中没有运行任何渲染代码...这很奇怪,因为渲染器几乎完全控制了性能,因此,如果每秒不对帧进行任何限制,则应使用稳定的蓝色淹没整个图形长方形。

    问题在于,探查器显示的代码只是调用我在上面选择的区域中的轮询输入和dll:

    c# - C#性能分析器显示了长时间的暂停,无法从提供的数据中确定它是什么-LMLPHP

    请注意,DispatchRenderFrame的另一个调用正在进行OpenGL调用,当我完全删除该调用时,它对程序没有影响,因此可以忽略该调用。这可能意味着下面看到的用户输入也不会影响微笔画问题...但是我无法删除它,因为它是我用于窗口管理(OpenTK)的库的一部分。

    我不确定CLR Worker线程是什么或正在做什么。它也发生在vsync一个(希望平滑分析一个)中,因此即使我不知道它是否是罪魁祸首,我也可能不是,但我不确定,因为它显示在“所需的vsync示例”也位于同一常规位置。

    是否发生了一些中断,操作系统正在接管但未恢复我的线程,因为它被归类为CPU吞噬?只是想一想...但是在示例中它再次显示为蓝色条,因此我认为Main线程实际上并未在我突出显示的内容中处于睡眠状态,并且实际上正在运行?

    如您所见,我不确定突出显示的时间段告诉我什么,以及我需要什么帮助。我不知道为什么此时代码中的等待百分比如此之高,或者从这里何处去进一步诊断问题。

    编辑:我对Stopwatch类进行了一些粗略的分析,以查看导致尖峰的位置,并且尖峰仅来自计算部分。 OpenGL调用均不会导致任何延迟。它纯粹是在执行数学运算和访问数据或写入预分配的结构数组的函数内部发生的。

    额外说明:

    这也让我感到好奇,是否有办法强制我使C#虚拟机获得尽可能多的CPU使用率?

    没有产生垃圾。这不是GC问题。我不能在申请期间运行GC,所以不会产生垃圾。渲染函数中的所有内容都是堆栈上的所有结构,唯一一次进入堆管理对象的是池化数组,其大小足以容纳所有渲染数据。它在事件探查器中出现的唯一时间是在开始和结束时,但是在渲染阶段不会运行。

    最佳答案

    出现峰值时,Windows 10任务栏是否有可能遮盖了您的应用程序窗口?我已经看到与此现象有关的严重口吃。我认为半透明任务栏的渲染意味着创建了屏幕外缓冲区,这会干扰任何关键帧的渲染循环。

    关于c# - C#性能分析器显示了长时间的暂停,无法从提供的数据中确定它是什么,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57541901/

    10-10 22:18