Kernel::Prof

NAME

Kernel::Prof – Perl profiling made easy

TODO

 nytprofmerge is sometimes failing:
    2023-09-27_10-27-28 [2076163] ERROR running 'nytprofhtml': 6400
    2023-09-27_10-27-28 [2076163] Sub Class::MOP::Method::Accessor::try {...}  already defined!
    Sub Devel::GlobalDestruction::in_global_destruction already defined!
    ...
    Can't call method "inc" on an undefined value at /home/tim/perl5/perlbrew/perls/perl-5.34.1/lib/site_perl/5.34.1/x86_64-linux/Devel/NYTProf/FileInfo.pm line 438.

 Apply ENV settings in a service file.

SYNOPSIS

Let's make profiling Perl code easy and simple as can be!

Below, CODE is placeholder for any code, such as:

    my $n = 0; for ( 1..10000 ){ $n+= $_ }

% is a command to be run on the command line (for triggers).

Profile a one-liner

OneShot

Generates the html results after the object goes out of scope.

% perl -MKernel::Prof -e 'my $p = Kernel::Prof->Run; CODE'

Triggered

Start recording after touch nytprof/work/start

Stop recording after touch nytprof/work/stop

    % perl -MKernel::Prof -E 'while(1){ my $p = Kernel::Prof->Run( UseTriggers => 1); say "HERE"; sleep 2 }'
    % perl -I. -MKernel::Prof -MMojo::MemoryMap -E 'my $m = Mojo::MemoryMap->new(); while(1){ my $p = Kernel::Prof->Run( UseTriggers => 1, MemoryMap => $m, CompressResults => 1, StopAfterNMinutes => 5 ); say "HERE"; sleep 5 }'

Profile a block of perl code:

    use Kernel::Prof;

    {
        my $ProfilerObject = Kernel::Prof->Run();
        CODE
    }

Profile using file triggers

    % touch nytprof/work/start

    use Kernel::Prof;
    my $ProfilerObject = Kernel::Prof->Run( UseTriggers => 1 );
    CODE

    % touch nytprof/work/stop

DESCRIPTION

This module is a tool that is designed to make profiling perl code as easy as can be.

Run Stages

 When profiling, keep in mind:
 - The stages described below.
 - the scope of what should be captured/recorded.

 Flow of Code Execution:

 |==          <-- Stage 1: Setup environment.
 |
 |====        <-- Stage 2: Beginning of code.
 |
 |========    <-- Stage 3: Start profiling.
 |
 |                (Data is collected/recorded ONLY here!)
 |
 |========    <-- Stage 4: Stop profiling.
 |
 |====        <-- Stage 5: End of code.
 |
 |==          <-- Stage 6: Restore environment
 |
 v

Stage 1: Setup Environment

These environmental variables should be setup. Failure to do so may result in missing links and/or data in the results!

    export PERL5OPT=-d:NYTProf
    export NYTPROF='trace=0:start=no:addpid=1:slowops=0'

    # Trace   - Set to a higher value like '1' for more details.
    # Start   - Put profiler into "standby" mode (ready, but not running).
    # AddPid  - Important when there are multiple processes.
    # SlowOps - Disabled to avoid profiling say `sleep` or `print`.

If running as a service, the environmental variables should be stored in the service file instead:

    systemctl status OTRS_WEBSERVICE_NAME
    sudo vi /etc/systemdsystem/OTRS_WEBSERVICE_NAME.service

Add this line:

    Environment="PERL5OPT=-d:NYTProf" "NYTPROF='trace=0:start=no:addpid=1:slowops=0'"

    systemctl restart OTRS_WEBSERVICE_NAME

Stage 2: Beginning of Code

 The C<profiler> at this point is in "standby" mode:
 - Aware of source files (important for later).
 - Not actually recording anything yet.

Stage 3: Start Profiling

To start profiling is like pressing a global record button. Anything after starting to profile will be stored in a file in a data format (which is mostly in machine-readable format).

Stage 4: Stop Profiling

Similary, to stop profiling is to press the global stop button.

NOTE: It is important to stop the profile correctly since the results would otherwise be useless. As stated in Devel::NYTProf:

 "NYTProf writes some important data to the data file when finishing profiling."

Stage 5: End of Code

 The C<profiler> at this point returns again to "standby" mode:
 - Aware of source files (maybe important for later).
 - Not actually recording anything anymore.

Stage 6: Restore Environment

Once profiling is done, the environment should be restored using:

    unset PERL5OPT
    unset NYTPROF

Run Modes

Run modes affect when the profiler should start and stop.

OneShot

This run mode is simpler, but perhaps less useful as well.

The profiler starts recording data after calling Run().

The profiler stops recording data after the return object goes out of scope (via DESTROY).

Therefore, make sure to assign the return object from Run() or the recorded data will be quite short 😉

    {
       my $ProfilerObject = Kernel::Prof->Run();
       ...
       CODE
    }

    # $ProfilerObject goes out of scope here and stops the recording.

Triggered

This run mode is a bit more complicated, but also more useful.

It relies on the existence of files on the system to determine when to start and to stop the recording of data.

The profiler starts recording data when Run() is invoked a "start" file has been detected.

The profiler stops recording data when the return object goes out of scope and a "stop" file has been detected.

NOTE: The start/stop of recording is a GLOBAL setting and may remain in effect past ProfilerObject destruction.

    while (...) {
       my $ProfilerObject = Kernel::Prof->Run(); # Would start recording
                                                 # if a "start" file exists.
       ...
       CODE
    }                                            # Would stop recording
                                                 # if a "stop" file exists.

METHODS

Run

Run the profiler and return a special ProfilerObject.

    my $ProfilerObject = Kernel::Prof->Run( %Options );

Will automatically close the recording data file when the ProfilerObject goes out of scope (by default).

Main Options

Values shown are the defaults.

    Name                    => "my",                   # Name/title of the results.
    UseTriggers             => 0,                      # Trigger mode: enable flag.
    StopAfterNMinutes       => 0,                      # Trigger mode: automatically stop after N minutes.
    MemoryMap               => Mojo::MemoryMap->new(), # For IPC (multiple processes).

NYTProf Build Options

    UseFlameGraph           => 0,                      # Generate the flame graph (slower).
    KeepAllFiles            => 0,                      # For debugging.
    CompressResults         => 0,                      # Generate a tar ball of the results and remove the data.
    CreateIndividualResults => 1,                      # Make also html per worker.
    CreateMergedResults     => 0,                      # Make also html based on all workers (might fail).

File/Folder Name Options

    RootName                => "mytprof",              # Root folder for all sub folders of results and triggers.
    WorkName                => "work",                 # Where raw data and file triggers are stored.
    WorkDir                 => "$RootName/$WorkName",  # Folder to store results.
    StartFlag               => "$WorkDir/start",       # File to tell the profiler to begin recording.
    StopFlag                => "$WorkDir/stop",        # File to tell the profiler to finish recording.
    NotifyFlag              => "$WorkDir/notify",      # Notification if profling active.
    Log                     => "$WorkDir/log",         # Proflier log.
Scroll to Top