The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.


DashProfiler::Core - DashProfiler core object and sampler factory


See DashProfiler::UserGuide for a general introduction.

DashProfiler::Core is currently viewed as an internal class. The interface may change. The DashProfiler and DashProfiler::Import modules are the usual interfaces.


A DashProfiler::Core objects are the core of the DashProfiler, naturally. They sit between the 'samplers' that feed data into a core, and the DBI::Profile objects that aggregate those samples. A core may have multiple samplers and multiple profiles.



  $obj = DashProfiler::Core->new( 'foo' );

  $obj = DashProfiler::Core->new( 'bar', { ...options... } );

  $obj = DashProfiler::Core->new( extsys => {
      granularity => 10,
      flush_interval => 300,
  } );

Creates and returns a DashProfiler::Core object.

Options for new()


Set to a true value to prevent samples being added to this core. If true, the prepare() method and the DashProfiler::Sample new() method will return undef.

Default false.

Currently, any existing samples that were active will still be added when they terminate. This behaviour may change.

See also DashProfiler::Import.


Specifies the class to use for creating DBI::Profile objects. The default is DBI::Profile. Alternatives include DBI::ProfileDumper and DBI::ProfileDumper::Apache.


Specifies extra arguments to pass the new() method of the dbi_profile_class (e.g., DBI::Profile). The default is { }.


How frequently the DBI:Profiles associated with this core should be written out and the data reset. Default is 0 - no regular flushing.


If set, this code reference is called when flush() is called and can influence its behaviour. For example, this is the flush_hook used by DashProfiler::Auto:

    flush_hook => sub {
        my ($self, $dbi_profile_name) = @_;
        warn $_ for $self->profile_as_text($dbi_profile_name);
        return $self->reset_profile_data($dbi_profile_name);

See "flush" for more details.


The default Path for the DBI::Profile objects doesn't include time. The granularity option adds '!Time~$granularity' to the front of the Path. So as time passes the samples are aggregated into new sub-trees.


The sample_class option specifies which class should be used to take profile samples. The default is DashProfiler::Sample. See the "prepare" method for more information.


Specifies the name of an extra DBI Profile object to attach to the core. This extra 'period summary' profile is enabled and reset by the start_sample_period() method and disabled by the end_sample_period() method.

The mechanism enables a single profile to be used to capture both long-running sampling (often with granularity set) and single-period (e.g., for a 'debug' footer on a generated web page)


When using periods, via the start_sample_period() and end_sample_period() methods, DashProfiler can add an additional sample representing the time between the start_sample_period() and end_sample_period() method calls that wasn't accounted for by the samples.

The period_exclusive option enables this extra sample. The value of the option is used as the value for key1 and key2 in the Path.


See "start_sample_period".


See "end_sample_period".


A reference to a hash containing default formatting arguments for the profile_as_text() method.


Can be used to attach any extra information to the profiler core object. That can be useful sometimes in callbacks.


  $sample_overhead_time = DashProfiler::Core->estimate_sample_overheads();

  ($sample_overhead_time, $sample_inner_time)
      = DashProfiler::Core->estimate_sample_overheads();

Estimates and returns the approximate minimum time overhead for taking a sample. Two times are returned. The following timeline diagram explains the difference:

    previous statement      -------------                              
    sampler called                    |                                
      sampler does work               |                                
      sampler reads time    -----     |                           
      sampler does work       |       |                           
      return sample object    |       |                           
                              |       |                           
    (measured statements)     |       |                           
                              |       |                           
    sample DESTROY'd          |       |                           
      sample does work        v       |                           
      sample reads time     -----     |     = sample_inner_time  
      sample does work                |                                
    next statement          -------------   = sample_overhead_time       

For estimate_sample_overheads() there are no measured statements so the times reflect the pure overheads.

Note that because estimate_sample_overheads() uses a tight loop, the timings returned are likely to be slightly smaller then the timings you'd get in practice due to CPU L2 caches and other factors. This is okay. On my 2GHz laptop running OS X 10.5.2 $sample_overhead_time is 0.000014 and $sample_inner_time is 0.000003. (When doing occasional sampling the sample_overhead_time is 0.000002 to 0.000003 higher, in case you care.)

DashProfiler automatically calls estimate_sample_overheads() when loading and records the returned values. It then uses the sample_overhead_time to adjust the "period_exclusive" time to more accrately reflect the time not covered by the accumulated samples. Currently the sample_inner_time is not subtracted from the individual samples. That may change in future.



  $core->attach_dbi_profile( $dbi_profile, $name );

Attaches a DBI Profile to a DashProfiler::Core object using the $name given. Any later samples are also aggregated into this DBI Profile.

Not normally called directly. The new() method calls attach_dbi_profile() to attach the "main" profile and the period_summary profile, if enabled.

The $dbi_profile argument can be either a DBI::Profile object or a string containing a DBI::Profile specification.

The get_dbi_profile($name) method can be used to retrieve the profile.


  $dbi_profile  = $core->get_dbi_profile( $dbi_profile_name );
  @dbi_profiles = $core->get_dbi_profile( '*' );

Returns a reference to the DBI Profile object that attached to the $core with the given name. If $dbi_profile_name is undef then it defaults to "main". Returns undef if there's no profile with that name atached. If $dbi_profile_name is '*' then it returns all attached profiles. See "attach_dbi_profile".


  $core->profile_as_text( $dbi_profile_name );
  $core->profile_as_text( $dbi_profile_name, {
      path      => [ $self->{profile_name} ],
      format    => '%1$s: dur=%11$f count=%10$d (max=%14$f avg=%2$f)'."\n",
      separator => ">",
  } );

Returns the aggregated data from the specified DBI Profile (default "main") formatted as a string. Calls "get_dbi_profile" to get the DBI Profile, then calls the as_text method on the profile. See DBI::Profile for more details of the parameters.

In list context it returns one item per profile leaf node, in scalar context they're concatenated into a single string. Returns undef if the named DBI Profile doesn't exist.


  $core->reset_profile_data( $dbi_profile_name );

Resets (discards) DBI Profile data and resets the period count to 0. If $dbi_profile_name is false then it defaults to "main". If $dbi_profile_name is "*" then all attached profiles are reset. Returns a list of the affected DBI::Profile objects.


  $core->visit_profile_nodes( $dbi_profile_name, sub { ... } )

Calls the given subroutine for each leaf node in the named DBI Profile. The name defaults to "main". If $dbi_profile_name is "*" then the leafs nodes in all the attached profiles are visited.


  $core->propagate_period_count( $dbi_profile_name )

Sets the count field of all the leaf-nodes in the named DBI Profile to the number of times start_sample_period() has been called since the last flush() or reset_profile_data().

If $dbi_profile_name is "*" then counts in all attached profiles are set.

Resets the period count used.

Does nothing but return 0 if the the period count is zero.

This method is especially useful where the number of sample periods are much more relevant than the number of samples. This is typically the case where sample periods correspond to major units of work, such as web requests. Using propagate_period_count() lets you calculate averages based on the count of periods instead of samples.

Imagine, for example, that you're instrumenting a web application and you have a function that sends a request to some network service and another reads each line of the response. You'd add DashProfiler sampler calls to each function. The number of samples recorded in the leaf node will depends on the number of lines in the response from the network service. You're much more likely to want to know "average total time spent handling the network service per http request" than "average time spent in a network service related function".

This method is typically called just before a flush(), often via flush_hook.


  $core->flush( $dbi_profile_name )

Calls the flush_hook code reference, if set, passing it $core and the $dbi_profile_name augument (which is typically undef). If the flush_hook code returns a non-empty list then flush() does nothing more except return that list.

If flush_hook wasn't set, or it returned an empty list, then the flush_to_disk() method is called for the named DBI Profile (defaults to "main", use "*" for all). In this case flush() returns a list of the DBI::Profile objects flushed.



Returns nothing if flush_interval was not set. Returns nothing if flush_interval was set but insufficient time has passed since the last call to flush_if_due(). Otherwise notes the time the next flush will be due, and calls return flush();.


    $bool = $core->has_profile_data
    $bool = $core->has_profile_data( $dbi_profile_name )

Returns true if the named DBI Profile (default "main") contains any profile data.



Marks the start of a series of related samples, e.g, within one http request.

If end_sample_period() has not been called for this core since the last start_sample_period() then the value of the period_strict_start attribute determines the actions taken:

  0 = restart the period, silently
  1 = restart the period and issue a warning (this is the default)
  2 = continue the current period, silently
  3 = continue the current period and issue a warning
  4 = call end_sample_period(), silently
  5 = call end_sample_period() and issue a warning

If the value is a CODE ref then it's called (and passed $core) and the return value used.

Resets the period_accumulated attribute to zero. Sets period_start_time to the current dbi_time(). If period_summary is enabled then the period_summary DBI Profile is enabled and reset.

See also "end_sample_period", the period_summary option, and "propagate_period_count".



Marks the end of a series of related samples, e.g, within one http request.

If start_sample_period() has not been called for this core since the last end_sample_period() (or the start of the script) then the value of the period_strict_end attribute determines the actions taken:

  0 = do nothing, silently (this is the default)
  1 = do nothing but warn
  2 = call start_sample_period(), silently
  3 = call start_sample_period() and warn

If the value is a CODE ref then it's called (and passed $core) and the return value used. If start_sample_period() isn't called then end_sample_period() just returns.

The period_count attribute is incremented.

If period_exclusive is enabled then a sample is added with a duration caclulated to be the time since start_sample_period() was called to now, minus the time accumulated by samples since start_sample_period() was called.

Resets the period_start_time attribute to 0. If period_summary is enabled then the period_summary DBI Profile is disabled and returned, else undef is returned.

See also "start_sample_period", period_summary and "propagate_period_count".


  $time = $core->period_start_time;

Returns the time the current sample period was started (typically the time "start_sample_period" was called) or 0 if there's no period active.


  $sampler_code_ref = $core->prepare( $context1 )
  $sampler_code_ref = $core->prepare( $context1, $context2 )
  $sampler_code_ref = $core->prepare( $context1, $context2, %meta )

  $sampler_code_ref->( $context2 )
  $sampler_code_ref->( $context2, $start_time )

Returns a reference to a subroutine that will create sampler objects. In effect the prepare() method creates a 'factory'.

The sampler objects created by the returned code reference are pre-set to use $context1, and optionally $context2, as their context values.

If the appropriate value for context2 won't be available until the end of the sample you can set $context2 to a code reference. The reference will be executed at the end of the sample. See DashProfiler::Sample.

XXX needs more info about %meta - see the code for now, it's not very complex.

See DashProfiler::Sample for more information.


The DEBUG subroutine is a constant that returns whatever the value of


was when the modle was loaded.


DashProfiler by Tim Bunce, and


The DashProfiler distribution is Copyright (c) 2007-2008 Tim Bunce. Ireland. All rights reserved.

You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file.