修复 UnrealInsights 帧率显示问题
UnrealInsights 是 UE4 新的性能分析工具,可以方便地实时 Profile 游戏性能。但是使用过程中发现一个问题,当游戏帧率稳定的时候,UnrealInsights 里显示的帧率仍然是上下波动的,如图
这样会对性能分析造成困扰,因为看不出哪里是真正的帧率波动了。经过修复后的帧率图如下
这样就能很容易看出哪里产生了性能问题
分析问题
产生这个问题的原因是 UnrealInsights 收集一帧耗时不正确,弄错了一帧的开始时间和结束时间。当在 UnrealInsights 中选择一帧的时候,它显示的范围如图
Insights 收集的一帧时间,实际上是前一帧的后半部分加上后一帧的前半部分,因此就造成实际帧率稳定平滑,但是 Insights 却显示的不平滑的问题
具体代码在 FEngineLoop::Tick
中,UnrealInsights 收集的一帧时间就是这个函数的总时间,但是实际上这个函数应该拆成两部分
第一个 SCOPE_CYCLE_COUNTER(STAT_FrameTime);
所处的代码块其实还是上一个 Tick
的内容,会计算上一个 Tick
的耗时和帧率,如果不超过 16ms(60帧) 或者 33ms(30帧),则会在 UpdateTimeAndHandleMaxTickRate
中进行 Sleep
来限制帧率
第二个 SCOPE_CYCLE_COUNTER(STAT_FrameTime);
代码块才是真正的的下一帧的开始,会在这里递增 GFrameCounter
。因此 UnrealInsights 收集 CPU 一帧的性能宏 TRACE_BEGIN_FRAME(TraceFrameType_Game)
和 TRACE_END_FRAME(TraceFrameType_Game)
,应该放在这里,如下
void FEngineLoop::Tick()
{
static bool bTraceStart = false; // 记录是否开始了 Trace
{
// TRACE_BEGIN_FRAME(TraceFrameType_Game); 注释掉原有的帧开始
SCOPE_CYCLE_COUNTER(STAT_FrameTime);
// 其他代码
// ...
}
if (bTraceStart)
{
TRACE_END_FRAME(TraceFrameType_Game); // 结束上一帧
}
bTraceStart = true;
TRACE_BEGIN_FRAME(STAT_FrameTime); // 开始下一帧
{
SCOPE_CYCLE_COUNTER( STAT_FrameTime );
// 其他代码
// ...
// TRACE_END_FRAME(TraceFrameType_Game); 注释原有的帧结束
}
}
这样收集的一帧时间戳就能和实际的帧率正确对应起来了,如图