Sub level streaming FPS drops

Franco,

Are you still testing this in

At a glance:

  1. Your Components*Granularity values are going to be a bottleneck. Only allowing a single component to be registered in a frame means that it will likely take many frames to load in a single sublevel (assuming your levels are not nearly empty).
  2. Your time limits are very small. These values are supposed to be specified in MIlliseconds. So, for example, 0.05 is only 50 microseconds. Similarly, the other time values seem very small. Again, this could (and likely will) lead to your levels taking a large number of frames.

Looking at the dump you provided, there are a few things that stand out.

The first hitch is ~121 ms. Most of that time is being spent in this block:

98.343ms (   1)  -  UpdateLevelStreaming Time - STAT_UpdateLevelStreamingTime - STATGROUP_StreamingDetails - STATCAT_Advanced
  98.325ms (  52)  -  LevelStreamingKismet/Game/Maps/ForestNew/FO_Main.FO_Main.LevelStreamingKismet - STATGROUP_UObjects - STATCAT_Advanced
    98.300ms (   1)  -  AddToWorld Time - STAT_AddToWorldTime - STATGROUP_StreamingDetails - STATCAT_Advanced
      98.299ms (   1)  -  Level/Game/Maps/ForestNew/FO_Tutorial_SCR.FO_Tutorial_SCR.PersistentLevel - STATGROUP_UObjects - STATCAT_Advanced
        73.827ms (   6)  -  LoadObject - STAT_LoadObject - STATGROUP_Object - STATCAT_Advanced
          69.349ms (   6)  -  Self

There are a few things that are odd about this. First, there’s no explicit LoadObject calls inside AddToWorld. By the time AddToWorld is called, it’s expected that the level (and all of it’s Actors, and all of their components) have already been loaded. Further, there are no stat groups below the Object scope.

This likely means that there’s something being triggered by Game Code somewhere that’s causing some other large load.

In AsyncLoading.h, we define PERF_TRACK_DETAILED_ASYNC_STATS. If you set that to 1 and recompile, we’ll print out detailed information about where time is being spent. This includes a bunch of more granular logs in AddToWorld. This may help you track down at what point in the process you’re actually spending those cycles.

The other hitches seem more like general things. Your Slate Tick Time generally seems high 11~12ms. In the final hitch, it’s up to ~41ms. That accounts for a large portion of the second hitch of ~30ms.

Another one of the hitches is from Garbage Collection.

Certain operations in level streaming are not done across multiple frames. For example, all Actors / Components will have BeginPlay called on the final frame, along with UpdateOverlaps.

Your spending a non-trivial amount of time in both of these. Potential things to help in that case:

  1. Limit heavy lifting done in BeginPlay.
  2. Make sure you only have GenerateOverlaps enabled for components that actually need it.

Thanks,
Jon N.