Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Resolved Enabling & visualizing profiling data only through script

Discussion in 'Scripting' started by Gluttonium, Jan 5, 2022.

  1. Gluttonium

    Gluttonium

    Joined:
    Aug 19, 2021
    Posts:
    31
    Well, hello there.
    I got some issues with enabling the Profiler through scripts. In essence what I'm trying to accomplish is to make profiling information visible on the Profiler window in the Unity Editor while only using scripts 'without' saving it to a file first. It is important that I want to manualy save the profiling information to a binary file by clicking it from within the profiler window. Bassically as in the figure below.

    upload_2022-1-5_15-36-39.png

    Enabling the profiler from script:
    Code (CSharp):
    1. Profiler.enabled = true;
    to kickstart the profiling process doesn't show any data inside the Profiler window (the recordbutton in this case was/will stay white). However when the recordbutton was manually pressed beforehand, enabling/disabling does result in data shown inside the Profiler window (the recordbutton in this case was/will stay red).

    I don't like the fact that I'm forced to manualy start profiling before I execute my profiling script in order to see it within the window and to be able to manualy save it.
    Any Suggestions to pull this off?
     
  2. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,431
    Hello,
    Due to the ProfilerWindow state overriding the recording state when doing this within the editor you also need to set
    Code (CSharp):
    1. UnityEditorInternal.ProfilerDriver.enabled = true;
    If that's in a script outside of an Editor Folder, remember to wrap that in
    #if UNITY_EDITOR
    and
    #endif
     
    Gluttonium likes this.
  3. Gluttonium

    Gluttonium

    Joined:
    Aug 19, 2021
    Posts:
    31
    Thanks alot for the answer! Although I hate to ask but, is possible to achieve this in Developmentbuilds with Autoconnected profilers?
     
  4. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,431
    Afaik yes. If the Profiler is connected, Profiler.enabled should be reflected back to the listening editor. It may have been broken in some older versions so just make sure you're on the latest patch release of whichever major Unity version you are using.
     
  5. Gluttonium

    Gluttonium

    Joined:
    Aug 19, 2021
    Posts:
    31
    Enabling the profiler through a script on a Developmentbuild with Autoconnected profiler does in my case not result in the profiling window showing any recorded data. Am I doing something wrong?
     
  6. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,431
    Does the profiler show it is connected to the player? And just to be certain, you are setting Profiler.enabled = true in the Player build?
     
  7. Gluttonium

    Gluttonium

    Joined:
    Aug 19, 2021
    Posts:
    31
    It does indeed show that the profiler is connected.

    I might be missing something, but the Profiler.enabled is set to true. Profiler.enabled also isn't wrapped in preprocessor directives. If configured in tandem with:
    Code (CSharp):
    1. string filepath = Application.persistentDataPath + "/profilerLog";
    2.  
    3. Profiler.logFile = filepath;
    4. Profiler.enableBinaryLog = true;
    It will save to the IndexedDB of my WebGL Devbuild, so it does work, but doesn't show it on the Autoconnected profiler window.
     
    Last edited: Jan 6, 2022
  8. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,431
    Right, sorry my bad, the fixes were that the ProfilerWindow is authoritive on the profiler enabled state if attached. So turning this on from the player doesn't work. But, you could have an Editor script Receiving a call from the player via PlayerConnection/EditorConnection API as the connection is alret established. With that you can message your script to turn on profiling in the editor. There is then a bit of a delay for the back and forth and profiling to start, but that could work?
     
    Gluttonium likes this.
  9. Gluttonium

    Gluttonium

    Joined:
    Aug 19, 2021
    Posts:
    31
    Just curious, could using the PlayerConnection/EditorConnection API perchance also allow me to directly log the profilingdata to my filesystem even though it's technically a WebGL build?
     
    Last edited: Jan 6, 2022
  10. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,431
    That connection is used by the profiler to send the data over so, technically you'd be using it that way but no, you can't directly reroute your profiler data through that connection directly to file, only via such an Editor script that would handle the editor side of recording and saving the files for you based on the messages send from the player
     
  11. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,431
    Gluttonium likes this.
  12. Gluttonium

    Gluttonium

    Joined:
    Aug 19, 2021
    Posts:
    31
    So if I understand this correctly, if I use the Editor/PlayerConnection to make the Player send a message to the Editor and based on said message, start profiling, then... the profiling-data recorded is based on the editor? I.e. like putting the profiler in 'Editor' mode instead of 'Playmode'?

    Edit
    : I made a script that sends a message from the Player that gets received by the Editor as an indication to start profiling. The profiler window will reflect the profiling data of the Player. However saving it through script resulted in saving profiling data of the 'Editor' instead of the 'Player'.

    The answer to this thread is already implied in the replies given by @MartinTilo, you can, visualize profiling data through scripts of Playmode by using:
    Code (CSharp):
    1. UnityEditorInternal.ProfilerDriver.enabled = true;
    Even in a development build it is possible as long as the profiler is enabled within an Editor script, which can be invoked using EditorConnection & PlayerConnection. Trying to save said information through scripts from within the editor results in saving profiling-data of the 'Editor' not the 'Player'.
     
    Last edited: Jan 11, 2022
  13. Gluttonium

    Gluttonium

    Joined:
    Aug 19, 2021
    Posts:
    31
    @MartinTilo so there is absolutely no way of saving the Players profiler-data of a Dev WebGL-build, other than the use of IndexedDB?
     
  14. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,431
    Gluttonium likes this.
  15. Gluttonium

    Gluttonium

    Joined:
    Aug 19, 2021
    Posts:
    31
    What I gather from this is that when one wants to enable the Player profiler through scripts on a WebGL development build and show said data on the ProfilerWindow of the Unity Editor AND save that shown data you use:
    Code (CSharp):
    1. UnityEditorInternal.ProfileDriver.enabled = true;
    2.  
    3. // Wait for signal to stop recording
    4. UnityEditorInternal.ProfileDriver.enabled = false;
    5. UnityEditorInternal.ProfilerDriver.SaveProfile(string fileName);
    Now I know this is going to contradict my main question posted in this thread and doesn't necessarily add anything to it BUT I realy want to check my options. If one would just use the following code from within an Editor script:
    Code (CSharp):
    1. // enable profiler and set the log file with a predefined string by default means
    2. Profiler.logFile = filepath;
    3. Profiler.enableBinaryLog = true;
    4. Profiler.enabled = true;
    would it with this code also be possible to log and save the Player profiling data? I myself tested this and it resulted in saving Editor profiling data to my filesystem. @MartinTilo, you mentioned
    I assume that I've taken this out of context but doesn't that mean that because a connection to the Player has been established through autoconnection that the secondary piece of code that is in this post should allow me to log the Players profiling data when executed from within an editor script? Why is it then that the Editor profiling data gets saved when using this method, or would it need an extra step?
     
    Last edited: Jan 11, 2022
  16. Gluttonium

    Gluttonium

    Joined:
    Aug 19, 2021
    Posts:
    31
    FYI, comming back to enabling the profiler through code using:
    Code (CSharp):
    1. UnityEditorInternal.ProfilerDriver.enabled = true;
    I noticed that enabling the profiler from within the Profilerwindow has a tendency to have slightly different measurements than doing it through said code (see attached image), could there be a reason for this?

    upload_2022-1-11_13-37-50.png
    (Before the dip in the rendering module it was enabled manualy, after the dip it is enabled through the ProfileDriver.)
     
  17. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,431
    Profiler.logFile directs the current app to stream it's profiling data to file instead of to the ProfilerWindow. If the Editor is getting data from the player, that's a different stream and won't go to the Editor's Profiler.logFile. Thats why that's not working.

    Hmm maybe more Profiler Modules are somehow set to record when recording is enabled via the API vs via UI? Profiler.SetAreaEnabled/GetAreaEnabled (on the Player side) or just adding all modules to the Profiler window with that 2 part profile in it may illuminate that part. If disabled modules show data after the dipp in the Rendering Module data, that's likely what it was. Also, Profiling overhead is categorized as Other and should be visible and attributed per module in the CPU Hierarchy (on the same level as the Player Loop) and in Timeline (the last ms of a frame on the Main Threads).

    (When starting to record via the UI, the Profiler Windows list of active modules (as ProfilerAreas) are send to the Player to enable their recording.)
     
    Gluttonium likes this.
  18. Gluttonium

    Gluttonium

    Joined:
    Aug 19, 2021
    Posts:
    31
    @MartinTilo It kinda works and kinda doesn't. When enabling the profiler for the first time there is a decent chance that It will function accordingly. However, it somehow isn't guaranteed and if the profiler gets enabled again after being disabled the profiler window simply won't record anything. Even events attached to the ProfileDriver.NewProfileFrameRecorded won't go off in those situations, perhaps simply because nothing is being profiled. Check the Editor Script below for some extra info.

    Edit: The EnableProfiler method gets called everytime there is a request to start profiling, invoking this always succeeds so the issue isn't there

    Code (CSharp):
    1. void OnEnable()
    2. {
    3.     // set callback on every frame that is recorded
    4.     UnityEditorInternal.ProfilerDriver.NewProfilerFrameRecorded += OnFrameRecorded;
    5. }
    6.  
    7. void OnDisable()
    8. {
    9.     // remove callback
    10.     UnityEditorInternal.ProfilerDriver.NewProfilerFrameRecorded -= OnFrameRecorded;
    11.  
    12.     // if still profiling disable that
    13.     if(_profiling)
    14.         DisableProfiler();
    15. }
    16.  
    17. private void OnFrameRecorded(int connectionId, int newFrameIndex)
    18. {
    19.     // Save data when the frameindex is multilpe of the shown framelimit
    20.     if(newFrameIndex % _settings.ProfilerFrameLimit == 0 && newFrameIndex != 0)
    21.     {
    22.         SaveProfile();
    23.         int totalRecordedFrames = _fileCount * _settings.ProfilerFrameLimit;
    24.  
    25.         // If more frames are recorded than the desired amount, disable profiler
    26.         if((totalRecordedFrames + newFrameIndex) >= _settings.TotalFrameCount)
    27.         {
    28.             DisableProfiler();
    29.         }
    30.     }
    31. }
    32.  
    33. private void EnableProfiler()
    34. {    
    35.     Debug.Log("Enabling Profiler");
    36.  
    37.     // Reset filecount
    38.     _fileCount = 0;
    39.  
    40.     // Clear frames before starting a new measurement
    41.     UnityEditorInternal.ProfilerDriver.ClearAllFrames();
    42.  
    43.     // enable profiler and set log file by controlling the profiling window
    44.     // is prone to breaking when changing/updating versions.
    45.     UnityEditorInternal.ProfilerDriver.enabled = true;
    46.     _profiling = true;
    47. }
    48.  
    49. private void DisableProfiler()
    50. {    
    51.     Debug.Log("Disable Profiler");
    52.          
    53.     UnityEditorInternal.ProfilerDriver.enabled = false;
    54.     _profiling = false;
    55. }
    56.  
    57. private void SaveProfile()
    58. {
    59.     Debug.Log("Save profiling data");
    60.  
    61.     string filepath = Application.persistentDataPath + "/" + _settings.FileName + "_" + _fileCount + ".data";
    62.     UnityEditorInternal.ProfilerDriver.SaveProfile(filepath);
    63.     _fileCount++;
    64.  
    65.     // Clear frames for next measurement
    66.     UnityEditorInternal.ProfilerDriver.ClearAllFrames();
    67. }