Mike AstleYAPC::Europe 2008
Copenhagen
http://artport.whitney.org/commissions/codedoc/Paley/CodeProfiles_800x600.htm
Profiling Perl
Profiling?● Recording / analyzing timing information about
program execution● General case code profilers record data by line,
sub, source file, etc. - inclusive vs. exclusive timings
● Domain-specific profilers record data about specific event types (e.g. SQL queries)
Some Ways Are More Equal Than Others
Devel::NYTProf – The New Hotness● Improved accuracy – Devel::DProf suffers from
a serious timing issue that makes its usefulness questionable
● Block level profiling – a Perl first● By far the most convenient and useful output
format – very much in keeping with the “Beautiful Perl” theme
● Good mod_perl integration
● Recursion causes over-counting of sub inclusive times – this can bite you hard
● Thread unsafe● caller() issue before 5.8.8● Does not count calls as a result of operator
overloading● goto &$sub not recognized as a sub call● no Windows support● Other suspicious output – got tests?
NYTProf - Open Issues
DBI::Profile and friends● DB usage is one of the most common forms of
optimization● Similar to a generic profiler, but with some very
DBI-specific parts● Impressive options list, easy to use
use DBI;
my $dsn = "DBI:mysql:database=” .
“uk_realestate;host=127.0.0.1;” .
“port=9308";
my $dbh = DBI->connect($dsn, 'root', '');
my $sth =
$dbh->prepare( 'select * from listings' .
' where id = ?' );
$sth->execute( 'id1' );
astle@mirth:~$ DBI_PROFILE='2' perl myprog.pl
DBI::Profile: 0.004590s (12 calls)
myprog.pl @ 2008-07-30 20:28:31
'' =>
0.004049s / 8 = 0.000506s avg
(first 0.003903s, min 0.000002s,
max 0.003903s)
'select * from listings where id = ?' =>
0.000541s / 4 = 0.000135s avg
(first 0.000068s, min 0.000018s,
max 0.000419s)
astle@mirth:~$ DBI_PROFILE='2' perl myprog.pl
DBI::Profile: 0.004481s (12 calls) myprog.pl
@ 2008-07-30 20:31:18
'' =>
'FETCH' => 0.000002s
'STORE' => 0.000114s / 4 = 0.000028s avg
(first 0.000011s, min 0.000008s, max 0.000086s)
'connect' => 0.003811s
'connected' => 0.000007s
'disconnect_all' => 0.000012s
'select * from listings where id = ?' =>
'DESTROY' => 0.000057s / 2 = 0.000028s avg
(first 0.000021s, min 0.000021s, max 0.000036s)
'execute' => 0.000406s
'prepare' => 0.000072s
With a little help from my friends● DBI::ProfilerDumper – writes out all timing data
to a file that can later be analyzed with CLI tool dbiprof
● DBI::ProfilerData – make your own output format
● DBI::ProfileDumper::Apache – you guessed it
DashProfiler
● A fast, lightweight instrumentation system● Built on DBI::Profile● Nothing is “free” – you have to set the data
collection points● Less overhead than a general profiler● Appropriate for live, code that must run fast● Happily gets on with mod_perl as well
use DashProfiler;
DashProfiler->add_profile( foo => { } );
DashProfiler->add_profile( foo => {
granularity => 10,
flush_interval => 600,
flush_hook => sub { ... },
sample_class => ‘DashProfiler::Sample’,
dbi_profile_class => ‘DBI::Profile’,
period_exclusive => ...,
period_summary => ..., } );
package MyModule;
use DashProfiler::Import
foo_profiler => [ ‘bar’ ];
sub my_sub {
my $value = shift;
my $sample = foo_profiler( $value )
if foo_profiler_enabled();
...send to $hostname...
}
DBI::Profile: 0.000027s 0.00% (2 calls) test-dash.pl @ 2008-08-12 13:32:15
'bar' =>
'baz' =>
0.000027s / 2 = 0.000013s avg
(first 0.000013s, min 0.000013s,
max 0.000014s)
● Fixes to known NYTProf problems
● Even more beautiful profiler output and visualizations
● More tests!● sub-microsecond
precision for DBI::Profiler
The Future?
Recommended