Skip to content

Adding StopProfile method to System.Runtime.ProfileOptimization class (MulticoreJit). #33426

@0xfk0

Description

@0xfk0

Issue description

Currently dotnet runtime (CoreCLR) has System.Runtime.ProfileOptimization class which is intendent to improve application startup performance (decrease startup time). ProfileOptimization class in just an interface to "MulticoreJIT" feature of dotnet runtime, which is implemented in scope of CoreCLR project.

The principle of operation of "MulticoreJIT" feature is to record "profile" -- which methods of which classes needs to be compiled during program startup, and later, when program is started second time, "replay" this profile: load necessary classes, and compile required methods in advance, in parallel thread.

Currently ProfileOptimization class implements only two methods:

  • void SetProfileRoot (string directoryPath);
  • void StartProfile (string profile).

First one sets directory, where profile should be stored. Second one specifies file name for the profile and starts recording and replaying the profile (if it was previously recorded).

It is obviously, that with such interface, consisting only of two functions, it's not clear when profiling should be stopped. Documentation says that:

The code that performs the recording tracks the rate at which methods are compiled, including methods that are compiled on both the background thread and on the main thread. When the rate falls below a predetermined level, recording stops. Recording also stops if the rate of JIT compilation exceeds a predetermined upper limit.

So where is no clear point at which profiling to be stopped before termination of the program. Only when program terminates the profile is guaranteed to be finished.

This leads us to two issues:

  1. some applications might never be stopped, for example, "server" applications, or long lived UI applications which is "minimized" to tray, but not closed -- for such applications profile might never be written to file;

  2. as there is no clear condition when profiling must be stopped, this might lead to recording of excess amount of profiling data and consequently to slowing down startup time (because of class loading and compiling the methods which, actually, not required for fast startup).

For last case I want to give an example: imagine computer game, which can be quickly started and then displays title screen, at which user can select game's level and press "start" button. After "start" button pressed, selected level is loaded (which requires loading lot of classes and compilation lot of methods). We want to stop recording profile just after title screen is shown, and we didn't want to record anything related to selected game level: because next time another level might be selected, and loading classes and compiling methods for level selected at previous time is waste of time.

Another example: GUI application, where some heavyweight function (which requires loading of many classes and compilation lot of methors) is started by user command. If the profiling isn't stopped at right time, the profile may include unwanted classes and methods.

To fight first issue (profile never written due to the fact, that dotnet runtime instance is never terminated) CoreCLR currently implements timeout, which might be tuned via environment variable COMPlus_MultiCoreJitProfileWriteDelay (default is 12 seconds). Unfortunately timeout
works only on Windows platform, but not on Unix (no code for this function in MulticoreJit component).

But solution with timeout not solves second issue: user might start gameplay within 12 second interval. And with any interval we always will be in question -- this inteval is too short, to record all required methods, or too long, to capture lot of unwanted methods.

Second issue and both examples listed above is the main reason for requesting extensions of the API: timeout isn't reliable way to control when profiling should be finished. We want to stop profiling at some exact state of the program, typically, when GUI application finished redrawing of main menu, title screen, etc...

Proposed solution

The proposition is to add into System.Runtime.ProfileOptimization class class a method with the following name and signature:

        public static void StopProfile();

This method should stop collecting the profile and save collected profile in the file pointed by StartProfile function (which should be previously called). By using this method, the application's creator might control exact period of time, at which profile is collected.

In most cases, for GUI applications, StartProfile is called after program start, and StopProfile should be called after displaying main window or initial screen of the application. For non GUI, "server" applications, StopProfile might be called after application entered in "main cycle" (accepting network connections, for example, etc...)

If StopProfile called when no StartProfile called before, or called twice, the function should do nothing.

If StopProfile isn't called at all, then "MulticoreJIT" feature's logic shouldn't be changed and profiling might be stopped by timeout, or at the program termination time.

Pull Request

The following pull request implements proposed changes: #33252

Also changes in documentation required, which should note existence of new function.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions