package VCP::Debug ;
=head1 NAME
VCP::Debug - debugging support for VCP
=head1 SYNOPSIS
=head1 DESCRIPTION
Debugging support for VCP. Enabled by setting the environment variable
VCPDEBUG=1.
=over
=cut
use VCP::Logger qw( lg pr log_file_name start_time );
use constant debugging => $ENV{VCPDEBUG} || 0;
use constant profiling => $ENV{VCPPROFILE} || 0;
BEGIN {
pr "debugging enabled, see ", log_file_name if debugging;
if ( profiling ) {
pr "profiling enabled, see ", log_file_name;
eval "use Time::HiRes qw( time ); 1"
or pr "Time::HiRes must be loaded for accurate profiling";
}
}
sub _secs($) { sprintf "%.6f secs", $_[0] }
sub _pct($$) {
$_[1] ? sprintf " (%5.2f%%)", 100 * $_[0] / $_[1] : "";
}
my %profile;
my %count;
my %groups;
END {
if ( profiling ) {
my $end_time = time;
my $elapsed = $end_time - start_time;
my $vcp_total = $elapsed;
my $non_vcp_total;
for my $group ( keys %groups ) {
for ( keys %profile ) {
if ( 0 == index $_, $group ) {
$profile{"${group}TOTAL"} += $profile{$_};
$vcp_total -= $profile{$_};
$count{"${group}TOTAL"} += $count{$_};
}
}
}
my @rows;
push @rows, [ "total time", "", _secs $elapsed, "" ];
push @rows, [ "VCP time", "", _secs $vcp_total, _pct $vcp_total, $elapsed ];
push @rows, [ $_, $count{$_} . " calls", _secs $profile{$_}, _pct $profile{$_}, $elapsed ]
for sort keys %profile;
my @w;
for ( @rows ) {
for my $i ( 0..$#$_ ) {
$w[$i] = length $_->[$i] if length $_->[$i] > ($w[$i] || 0);
}
}
my $f = " " . join " ", "%-$w[0]s:", map "%${_}s", @w[1..$#w];
lg "profiling report:";
lg sprintf $f, @$_ for @rows;
}
}
@ISA = qw( Exporter ) ;
my @DEBUG_EXPORTS = qw( debug debugging );
my @PROFILE_EXPORTS = qw( profile_end profile_start profile_group profiling );
@EXPORT_OK = ( @DEBUG_EXPORTS, @PROFILE_EXPORTS );
%EXPORT_TAGS = (
'all' => \@EXPORT_OK,
'debug' => \@DEBUG_EXPORTS,
'profile' => \@PROFILE_EXPORTS,
) ;
$VERSION = 0.1 ;
use strict ;
use vars qw( $profile_category );
use Exporter ;
# TODO:
#=item use
#=item import
#
#In addition to all of the routines and tags that C<use> and C<import> normally
#take (see above), you may also pass in pairwise debugging definitions like
#so:
#
# use VCP::debug (
# ":all",
# DEBUGGING_FOO => "foo,bar",
# ) ;
#
#Any all caps export import requests are created as subroutines that may well be
#optimized away at compile time if "enable_debugging" has not been called. This
#requires a conspiracy between the author of a module and the author of the main
#program to call enable_debugging I<before> C<use>ing any modules that leverage
#this feature, otherwise compile-time optimizations won't occur.
#
=item debug
debug $foo if debugging $self ;
Emits a line of debugging (a "\n" will be appended). Use
to avoid the "\n". Any undefined parameters will be displayed as
C<E<lt>undefE<gt>>.
=cut
sub debug {
return unless debugging != 0;
unshift @_, (caller 1)[3], "() ";
goto ≶
}
=item debugging
debug "blah" if debugging ;
Returns TRUE if the caller's module is being debugged
debug "blah" if debugging $self ;
debug "blah" if debugging $other, $self ; ## ORs the arguments together
Returns TRUE if any of the arguments are being debugged. Plain
strings can be passed or blessed references.
=cut
=item profiling
Returns true if VCP is profiling itself compared to shell command
performance.
This is different from using perl's profilers (-d:DProf and the like);
this profiling tracks the operation of some of VCP's internals and
also how long is spent waiting for child processes to complete.
=cut
=item $VCP::Debug::profile_category
Sets the category for the next profile_start and profile_end
pair of calls:
local $VCP::Debug::profile_category = "p4 files" if profiling;
=cut
=item profile_start
Notes the current time as the start of a profiling interval.
Defaults to the category $profile_category if none passed.
=cut
my %start_times;
sub profile_start {
my $key = @_ ? shift : $profile_category;
++$count{$key};
$start_times{$key} = time;
}
=item profile_end
Notes the current time as the end of a profiling interval.
Defaults to the category $profile_category if none passed.
=cut
sub profile_end {
my $time = time;
my $key = @_ ? shift : $profile_category;
my $elapsed = $time - delete $start_times{$key};
$profile{$key} += $elapsed;
## Make all times exclusive
$_ += $elapsed for values %start_times;
}
=item profile_group
Called with the prefix of a set of profile categories to sum up and
emit subtotals for.
=cut
sub profile_group {
$groups{$_[0]} = 1;
}
=back
=head1 COPYRIGHT
Copyright 2000, Perforce Software, Inc. All Rights Reserved.
This module and the VCP package are licensed according to the terms given in
the file LICENSE accompanying this distribution, a copy of which is included in
L<vcp>.
=head1 AUTHOR
Barrie Slaymaker <barries@slaysys.com>
=cut
1
syntax highlighted by Code2HTML, v. 0.9.1