Allow filtering release build-working ProfilerRecorderDescriptions

Hey guys,

I’m working on an Advanced FPS Counter plugin Profiler Counter module and would love to be able to find out which Profiler Stats are available at the release builds.

Currently, we have a MarkerFlags.AvailabilityEditor which allows filtering out all editor-only stats, but it would be awesome to see something like MarkerFlags.AvailabilityReleaseBuild in order to make it easier for FPS Counter users to pick runtime-only stats from the all stats list.

For now, I’m going to separate runtime-available stats by hands following docs and leave all non-editor stats available for users:
7610011--945280--gif.gif

But would appreciate a lot the possibility to filter out all release build stats automatically.
I’m not sure if something like this is already on track internally, perhaps @karl_jones QoL improvements wizard could chime in and help get this on track? =)

1 Like

Thanks for the question!

This is an oversight of the C# api surface - we have the flag for release markers/counters which is 1<<3 and you can also see it in the plugin api header (IUnityProfiler.h)

    kUnityProfilerMarkerFlagAvailabilityNonDev = 1 << 3, // Non-development marker, is present everywhere including release builds.

We’ll fix the C# bindings :slight_smile:

3 Likes

What a relief, Alexey, thank you so much!

I’ve just checked, and it seems not all non-dev stats are actually having this flag set, or I’m just doing something wrong %)

Here is how I’ve checked for the flag;

if (((ushort)description.Flags & (1 << 3)) != 0)
{
    // ...
}

Full code snippet:

void Start()
{
    var availableHandles = new List<ProfilerRecorderHandle>();
    ProfilerRecorderHandle.GetAvailable(availableHandles);

    var allStatsLog = "All stats available:\n";
    var nonDevStatsLog = "Stats for non dev build:\n";
 
    foreach (var recorderHandle in availableHandles)
    {
        var description = ProfilerRecorderHandle.GetDescription(recorderHandle);
        var statString = $"{description.Category}:{description.Name}\n";
        allStatsLog += statString;
     
        if (((ushort)description.Flags & (1 << 3)) != 0)
        {
            nonDevStatsLog += statString;
        }
    }
 
    Debug.Log(allStatsLog);
    Debug.Log(nonDevStatsLog);
}

And this is what I’m seeing in the log from the non-dev build (made with Unity 2022.1.0a13, but it’s similar in 2020.3 as well):

All stats available

VFX:VFX.ParticleSystem.RenderMeshIndirect
VFX:VFX.ParticleSystem.RenderMesh
VFX:VFX.ParticleSystem.RenderHexahedronIndirect
VFX:VFX.ParticleSystem.RenderHexahedron
VFX:VFX.ParticleSystem.RenderOctagonIndirect
VFX:VFX.ParticleSystem.RenderOctagon
VFX:VFX.ParticleSystem.RenderQuadIndirect
VFX:VFX.ParticleSystem.RenderQuad
VFX:VFX.ParticleSystem.RenderTriangleIndirect
VFX:VFX.ParticleSystem.RenderTriangle
VFX:VFX.ParticleSystem.RenderLineIndirect
VFX:VFX.ParticleSystem.RenderLine
VFX:VFX.ParticleSystem.RenderPointIndirect
VFX:VFX.ParticleSystem.RenderPoint
VFX:VFX.ParticleSystem.PerStripUpdate
VFX:VFX.ParticleSystem.Update
VFX:VFX.ParticleSystem.Init
VFX:VFX.MeshSystem.Render
VFX:VFX.SortBuffer
VFX:VFX.ZeroInitializeBuffer
VFX:VFX.InitializeDeadListBuffer
VFX:VFX.CopyBuffer
VFX:VFX.FillIndirectRenderArgs
VFX:VFX.ProcessCamera
VFX:VFX.PrepareCamera
Render:Gfx.WaitForPresentOnGfxThread
GC:GC.Collect
Loading:none-1
Loading:none
Render:RenderLoopDevice.Idle
Internal:profiler.Callstack
Scripts:
Internal:Main Thread
Other:
PlayerLoop:playerLoop
Render:CommandBuffer.Cleanup
Render:CommandBuffer.Execute
Render:CommandBuffer.Prepare
Render:Render.MotionVectors
Render:Render.TransparentGeometry
Render:Render.OpaqueGeometry
Render:Camera.Render
Memory:System Used Memory
Memory:Total Used Memory
Memory:Total Reserved Memory
Memory:GC Used Memory
Memory:GC Reserved Memory
Memory:profiler Used Memory
Memory:profiler Reserved Memory
Memory:Audio Used Memory
Memory:Audio Reserved Memory
Memory:Video Used Memory
Memory:Video Reserved Memory
Render:Render Textures Count
Render:Render Textures Bytes
Render:Batches Count
Render:smile:raw Calls Count
Render:Triangles Count
Render:Vertices Count
Render:SetPass Calls Count
Render:Shadow Casters Count
Render:Visible Skinned Meshes Count
Render:Render Textures Changes Count
Render:Used Buffers Count
Render:Used Buffers Bytes
Render:Vertex Buffer Upload In Frame Count
Render:Vertex Buffer Upload In Frame Bytes
Render:Index Buffer Upload In Frame Count
Render:Index Buffer Upload In Frame Bytes
Render:Video Memory Bytes

Stats for non dev build

Render:Gfx.WaitForPresentOnGfxThread
GC:GC.Collect
Internal:Main Thread
Other:
PlayerLoop:playerLoop
Render:smile:raw Calls Count
Render:Triangles Count
Render:Vertices Count
Render:SetPass Calls Count
Render:Shadow Casters Count

Seeing same short list when checking this flag in Editor.

Did I miss something or checking for the flag incorrectly?

No, your code looks good - we’ve missed something here.
We’ll also sync flags with the doc so that it is easier for you to process. Sorry for the inconvenience :frowning:

2 Likes

No worries and thanks for the quick reply!

I’ve just reported this (Case 1376913) with a repro project attached, hope that helps!

3 Likes

I’ve reported another case (1377242) with similar issue - not all Editor-only ProfilerRecorderDescriptions have
MarkerFlags.AvailabilityEditor flag set, for example whole Build Interface category (29) do not have that flag set.

2 Likes

Hello,
Thanks for flagging this. Though the case of the MarkerFlags.AvailabilityEditor flag is likely a bit of a miscommunication, faulty naming or misconception of our part. We use that one to be able to hide GC.Alloc samples occuring within children of samples flagged with it. Actually, we cut of the entire child sample stack under those samples in Hierarchy view unless you opt to have these Editor Only markers not collapsed. This was mostly conceived to hide confusing/misleading GC Allocs that would be prone to showing up in your Play Mode profile but which reside in code paths within Non-UnityEditor Assemblies that wouldn’t actually allocate (or even get executed) in a built Player.

For the Build Interface category, I guess you can just exclude the entire category if you want to get a clearer list of them, but there is nothing that would cleanly separate if the samples come from an Editor or a Player Assembly (outside of C# auto-instrumented samples I guess, those report their fully qualified type name with the assembly, so one could parse their name…)

Granted, I’m not sure if that is a valid enough explanation or reason though, gotta ponder that a bit, but it’s technically By Design.

1 Like

Hi Martin and thank you so much for chiming in with all those details about MarkerFlags.AvailabilityEditor flag.

Looks like this comment at IUnityProfiler.h and what I see in docs are kind of misleading (or initial idea was correct, but it wasn’t implemented that way afterwards?):
7620784--947683--upload_2021-11-1_22-26-55.png

Now I see I totally misunderstood its purpose, and it seems there is no way to filter out Editor-only samples for now which is a bit sad since to do this I’ll need to manually build up editor-only profiler recorders list by comparing recorder description lists in Editor and built dev players for all platforms, for all Unity versions which is a bit too much even for me =D

Thus, for now I’m going to end up with full unfiltered list in my plugin, so customers could pick by themselves, thankfully I’ve already figured out which samples are available in non-dev builds which is more important in my case, but may I ask kindly if everything we discussed earlier about kUnityProfilerMarkerFlagAvailabilityNonDev flag is still correct and once fixed and propagated into the C#, it will really allow filtering out non-dev profiler recorder descriptions?

1 Like

Nah, the comment and docs are correct. They are just not clear that the flag doesn’t mean that anything not flagged with it would appear in a player, just that the few samples that are flagged are guaranteed not to appear there.

Regarding non-dev makers and counters:
Release ProfilerMarkers are statically ensured to be flagged as non dev markers (via behavior and API/C++ Macro compile time availability). Release ProfilerCounters are not yet ensured in the same way, which is how this bug came about. Besides fixing the current situation, we’ll see what we can do to ensure correct flagging statically or via tests here too.

1 Like

Got it now, thank you a ton!

1 Like