Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Creating a [UnityProfiler] attribute for simpler Profiling in Unity

Discussion in 'Scripting' started by mhgamework, Jul 30, 2019.

  1. mhgamework

    mhgamework

    Joined:
    Dec 13, 2014
    Posts:
    13
    I am looking for a way to easily add "Profiler.BeginSample()/Profiler.EndSample()" to methods i choose in my application. I really like the default behaviour of unity where the Monobehaviour methods automatically show up in the profiler without cluttering my code. I would like to have something similar for custom code, since we are mostly not using monobehaviours since most of our computations are tied up in systems that loop over plain c# objects.

    I would prefer to have a simple [UnityProfiler] attribute that surrounds the method body with the begin and end calls, like some kind of code weaver or Aspect oriented programming approach.

    Currently i am using "Profiler.BeginSample()/Profiler.EndSample()" in most of my code with these problems
    • I have to be very careful to match up beginsample and endsample. return statements and coroutines can make it very hard to see problems here and a mistake is easily made. In case i make a mistake, there is no easy way to find the problem without doing a manual binary search over all my code. Since i am calling all my systems from a single monobehaviour run, this can easily take over half an hour to find a mismatch.
    • I simply want to use BeginSample("{classname}.{method}"), like unity is using for its defaultprofilers. I now have to manually keep this in sync.
    • To be correct, i should add try/finally blocks for each of these sample blocks. I am currently not doing this as my code is already getting cluttered enough, but it is another problem in the back of my mind.
    Does anyone know of a simpler/more reliable way, or some easy to use code manipulation tools or weaving mechanics for unity?

    MH
     
    firelight_jaden likes this.
  2. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,160
    Hello MH,

    Thanks for raising this topic, this is valuable feedback and I'll include it into the other feedback we've received to inform our (the Profiler Team's) Roadmap.

    While I do understand the kind of feature you are describing, I'd like to dig a bit deeper to make sure I captured the Problem you are trying to solve adequately:

    You mentioned, that you're not using the automatically instrumented MonoBehaviour methods: Is there a recurring theme or pattern behind the classes, methods or other structures you have in place and would you want all methods that fall under that pattern to be automatically profiled?
    E.g. are they all just one layer deeper than the Automatic instrumentation reaches? Are they all getting called from a central place? are they all in a specific folder, namespace, assembly, job system..? etc...

    Do you want to add these tags only to methods you'd like to profile? Or in other words, should it "propagate" to underlying methods, or would you rather have it restricted to the method scope to keep profiling overhead / compiletime low?

    Is having to edit your scripts an acceptable way to get these?

    I guess that covers most of my questions. Now, regarding yours:

    you cold switch to the newer ProfilerMarker API and use the
    Auto
    scope within a using statement. That way you don't have to worry about early returns or exceptions and a resulting bissmatch between begins and ends.

    Also in 2019.3.0a12 or newer, you can build players with deep profiling capabilities so you can toggle that on or of as you need to, or if you're mainly interested in GC.Alloc calls, you could switch on Call Stack collection for GC.Alloc samples. Those then show up in Timeline view as you select these samples, or in Hierarchy view by selecting objects related to GC.Alloc samples in the "Show Related Objects" view ("hidden" under the "no details" drop-down) (Note, this feature is older than 19.3 but was previously limited to profiling in the Editor)
     
  3. mhgamework

    mhgamework

    Joined:
    Dec 13, 2014
    Posts:
    13
    Thanks for your response, I've put the answers to your questions below.
    I will probably start using the ProfilerMarker api with the using statement as solves the mismatching of tags problem.

    However, the using statement and the additional field will still create clutter i would prefer not to have, so something like this would be alot simpler:
    Code (CSharp):
    1. [UnityProfile]
    2. public void MyCostlyCalculation(){
    3.    /// some code
    4. }
    I saw that the ProfilerMarker uses a struct implementing IDisposable, I'm guessing this does not get boxed on the heap?

    Answers to questions:

    Is there a recurring theme or pattern behind the classes, methods or other structures you have in place and would you want all methods that fall under that pattern to be automatically profiled?

    Not at this point no. They tend to be at the root of my simulation loop, but there are also deeper blocks for example for resource loading or occasional calculations in response to events.

    My current process for deciding what to profile is as follows:

    When i discover a piece of code that is "heavy" i mark using the begin/endsample. This way, when i do optimizations later i can easily discover the pieces of the system that are contributing most to performance problems.
    Another thing i do is regularly check that there is no "hidden time" in the unity profiler. When opening the profiler, i want to be able to quickly see which subsystems or features are eating up the frame time.


    Do you want to add these tags only to methods you'd like to profile? Or in other words, should it "propagate" to underlying methods, or would you rather have it restricted to the method scope to keep profiling overhead / compiletime low?

    I want to select specific methods, with the exact reason of keeping the overhead low.
    I want keep these profiler tags in the game so i can always easily see whats going on, so i only but them on blocks of code that process multiple entities or bigger blocks of data so that profiler overhead is negligible.

    Is having to edit your scripts an acceptable way to get these?

    Yes, I want the choices of which methods to profile to be saved in my version control system with the code, so probably prefer editing my scripts.
    However, i way to quickly add/remove methods to the profiler while the game is running could be a timesaver when finding new costly points in the code.
     
  4. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,160
    Cool, thank you for the detailed feedback :)

    And yes, there should be no Boxing or GC alloc going on for the disposable. :)
     
  5. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,741
    Not just overhead (though that is a factor), but additional clutter in the profiler stacks makes it harder to zero in on the one thing you're actually trying to profile.
     
    MartinTilo likes this.
  6. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    937
    I would like to add that an attribute on method scope as suggested by mhgamework would be great. Preferably, without any parameters the tag that shows up in the profiler would be 'class.methodname' and not propagate deeper into other methods. I'd also like to be able to specify a custom name and a custom propagation depth as an attribute parameter. Maybe also allow to put the attribute on the class scope to profile all the methods of that class.

    Furthermore, I agree that editing scripts to add profile markers is fine as I usually like to profile the same bits of code throughout development. An option in the profiler window to temporarily disable some of the costly profiler markers would also be nice though.
     
  7. brownboot67

    brownboot67

    Joined:
    Jan 5, 2013
    Posts:
    375
    +1 this would be a great feature.
     
  8. Spemble

    Spemble

    Joined:
    Mar 20, 2016
    Posts:
    7
    Is it possible to manually create this attribute ourselves?

    (Preliminary searches suggest not, as it seems attributes in C# are metadata and do not provide actions, so my guess is that this would have to be an addition to the compiling process or something.)