Author: tim.bunce
Date: Tue Oct 21 15:51:10 2008
New Revision: 530
Added:
trunk/t/test20-streval.p
trunk/t/test20-streval.rdt
Modified:
trunk/Changes
trunk/MANIFEST
trunk/lib/Devel/NYTProf/Data.pm
trunk/t/test09.rdt
trunk/t/test13.rdt
Log:
Add migration of sub_caller data from eval fids. (big missing feature)
Consolidate caches and provide a method to access and clear them.
Add method to return hash of eval fid to base fid mapping.
Add method to return hash of subs called by a fid.
Add method to delete data of subs called by a fid.
Modified: trunk/Changes
==============================================================================
--- trunk/Changes (original)
+++ trunk/Changes Tue Oct 21 15:51:10 2008
@@ -11,6 +11,10 @@
Now builds on Windows, with thanks to Jan Dubois!
+ Subroutine calls made from within string evals (and even
+ string evals within string evals etc) are now shown
+ in reports.
+
XS subs (xsubs) are now automatically associated with a source
file that defines normal subs in the same package.
Callers and timing information for xsubs are now shown at the
Modified: trunk/MANIFEST
==============================================================================
--- trunk/MANIFEST (original)
+++ trunk/MANIFEST Tue Oct 21 15:51:10 2008
@@ -75,6 +75,8 @@
t/test16.p
t/test16.rdt
t/test16.x
+t/test20-streval.p
+t/test20-streval.rdt
t/test30-fork.0.p
t/test30-fork.0.rdt
t/test30-fork.0.x
Modified: trunk/lib/Devel/NYTProf/Data.pm
==============================================================================
--- trunk/lib/Devel/NYTProf/Data.pm (original)
+++ trunk/lib/Devel/NYTProf/Data.pm Tue Oct 21 15:51:10 2008
@@ -91,6 +91,43 @@
(my $sub_class = $class) =~ s/\w+$/ProfSub/;
$_ and bless $_ => $sub_class for values %$sub_subinfo;
+
+ # migrate sub calls made from evals to be calls from the base fid
+ #
+ # map of { eval_fid => base_fid, ... }
+ my $eval_fid_map = $profile->eval_fid_map;
+ # map of { fid => { subs called from fid... }, ... }
+ my $fid_sub_calls_map = $profile->fid_sub_calls_map;
+ #
+ while ( my ($eval_fid, $base_fid) = each %$eval_fid_map ) {
+ my $subnames = $fid_sub_calls_map->{$eval_fid}
+ or next; # no subs called from this eval fid
+
+ # drill thru string-evals-within-string-evals
+ $base_fid = $eval_fid_map->{$base_fid}
+ while $eval_fid_map->{$base_fid};
+
+ my $line_of_eval = $profile->fileinfo_of($eval_fid)->eval_line;
+ warn "Migrating sub calls from eval fid $eval_fid to fid $base_fid
line $line_of_eval: @$subnames\n"
+ if $trace;
+
+ my $sub_caller = $profile->{sub_caller};
+ for my $subname (@$subnames) {
+
+ my $eval_calls = delete $sub_caller->{$subname}{$eval_fid}
+ or die "panic";
+ my $base_calls = $sub_caller->{$subname}{$base_fid} ||=
{};
+
+ warn "merged $subname calls from fid $eval_fid to $base_fid\n";
+ while ( my ($line_in_eval, $eval_line_calls) =
each %$eval_calls ) {
+ my $e = $eval_calls->{$line_in_eval};
+ my $b = $base_calls->{$line_of_eval} ||= [ (0) x @$e ];
+ $b->[$_] += $e->[$_] for ([EMAIL PROTECTED]);
+ }
+ }
+ }
+ $profile->_clear_caches;
+
# XXX merge evals - should become a method optionally called here
# (which uses other methods to do the work and those methods
# should also be called by Devel::NYTProf::ProfSub::callers())
@@ -153,10 +190,14 @@
}
}
}
+ $profile->_clear_caches;
return $profile;
}
+sub _caches { return shift->{caches} ||= {} }
+sub _clear_caches { return delete shift->{caches} }
+
sub all_subinfos {
my @all = values %{ shift->{sub_subinfo} };
return @all;
@@ -188,6 +229,30 @@
return $self->{fid_fileinfo}[$fid];
}
+sub eval_fid_map {
+ my $self = shift;
+ my $fid_fileinfo = $self->{fid_fileinfo} || [];
+ my $eval_fid_map = {};
+ for my $fileinfo (@$fid_fileinfo) {
+ my $base_fid = $fileinfo && $fileinfo->eval_fid
+ or next;
+ $eval_fid_map->{ $fileinfo->fid } = $base_fid;
+ }
+ return $eval_fid_map;
+}
+
+sub fid_sub_calls_map {
+ my $self = shift;
+ my $sub_caller = $self->{sub_caller} || {};
+ my $fid_sub_calls_map = {};
+ while ( my ($subname, $fid_hash) = each %$sub_caller ) {
+ for my $fid (keys %$fid_hash) {
+ push @{ $fid_sub_calls_map->{$fid} }, $subname;
+ }
+ }
+ return $fid_sub_calls_map;
+}
+
sub inc {
@@ -291,6 +356,7 @@
my $filehandle = $args->{filehandle} || \*STDOUT;
my $startnode = $args->{startnode} || $self; # undocumented
croak "Invalid startnode" unless ref $startnode;
+ $self->_clear_caches;
_dump_elements($startnode, $separator, $filehandle, []);
}
@@ -401,10 +467,7 @@
}
}
- # remove sub_caller info for calls made from within this file
- if (my $sub_caller = $self->{sub_caller}) {
- delete $_->{$fid} for values %$sub_caller;
- }
+ $fileinfo->delete_subs_called_info;
}
@@ -532,7 +595,8 @@
sub _filename_to_fid {
my $self = shift;
- return $self->{_filename_to_fid_cache} ||= do {
+ my $caches = $self->_caches;
+ return $caches->{_filename_to_fid_cache} ||= do {
my $fid_fileinfo = $self->{fid_fileinfo} || [];
my $filename_to_fid = {};
for my $fid (1 .. @$fid_fileinfo - 1) {
@@ -552,7 +616,7 @@
in a source file. The $file argument can be an integer file id (fid) or a
file
path. If $file is 0 then details for all known subroutines are returned.
-Returns undef if the profile contains no C<sub_caller> data for the $file.
+Returns undef if the profile contains no C<sub_subinfo> data for the $file.
The keys of the returned hash are fully qualified subroutine names and the
corresponding value is a hash reference containing
L<Devel::NYTProf::ProfSub>
@@ -565,15 +629,15 @@
=cut
-
sub subs_defined_in_file {
my ($self, $fid, $incl_lines) = @_;
$fid = $self->resolve_fid($fid);
$incl_lines ||= 0;
$incl_lines = 0 if $fid == 0;
+ my $caches = $self->_caches;
my $cache_key = "_cache:subs_defined_in_file:$fid:$incl_lines";
- return $self->{$cache_key} if $self->{$cache_key};
+ return $caches->{$cache_key} if $caches->{$cache_key};
my $sub_subinfo = $self->{sub_subinfo}
or return;
@@ -593,8 +657,8 @@
}
}
- $self->{$cache_key} = \%subs;
- return $self->{$cache_key};
+ $caches->{$cache_key} = \%subs;
+ return $caches->{$cache_key};
}
@@ -787,12 +851,14 @@
or return;
my $line_calls = {};
- while (my ($sub, $fid_hash) = each %$sub_caller) {
+ # search through all subs to find those that were called
+ # from the fid we're interested in
+ while (my ($subname, $fid_hash) = each %$sub_caller) {
my $line_calls_hash = $fid_hash->{$fid}
or next;
while (my ($line, $calls) = each %$line_calls_hash) {
- $line_calls->{$line}{$sub} = $calls;
+ $line_calls->{$line}{$subname} = $calls;
}
}
@@ -811,6 +877,11 @@
}
+sub _dumper {
+ require Data::Dumper;
+ return Data::Dumper::Dumper(@_);
+}
+
## --- will move out to separate files later ---
# for now these are viewed as private classes
@@ -888,6 +959,17 @@
$values[0] = $self->filename_without_inc;
pop @values; # remove profile ref
return [EMAIL PROTECTED];
+ }
+
+ sub delete_subs_called_info {
+ my $self = shift;
+ my $profile = $self->profile;
+ my $sub_caller = $profile->{sub_caller}
+ or return;
+ my $fid = $self->fid;
+ # remove sub_caller info for calls made *from within* this file
+ delete $_->{$fid} for values %$sub_caller;
+ return;
}
} # end of package
Modified: trunk/t/test09.rdt
==============================================================================
--- trunk/t/test09.rdt (original)
+++ trunk/t/test09.rdt Tue Oct 21 15:51:10 2008
@@ -54,8 +54,7 @@
profile_modes fid_line_time line
profile_modes fid_sub_time sub
sub_caller main::bar 1 13 [ 1 0 0 0 0 0 0 ]
-sub_caller main::bar 2 3 [ 1 0 0 0 0 0 0 ]
-sub_caller main::bar 4 3 [ 1 0 0 0 0 0 0 ]
+sub_caller main::bar 1 2 [ 2 0 0 0 0 0 0 ]
sub_caller main::foo 1 11 [ 1 0 0 0 0 0 0 ]
sub_caller main::foo 1 12 [ 1 0 0 0 0 0 0 ]
sub_subinfo main::bar [ 1 7 9 3 0 0 0 0 ]
Modified: trunk/t/test13.rdt
==============================================================================
--- trunk/t/test13.rdt (original)
+++ trunk/t/test13.rdt Tue Oct 21 15:51:10 2008
@@ -49,7 +49,7 @@
sub_caller main::baz 1 21 [ 1 0 0 0 0 0 0 ]
sub_caller main::foo 1 13 [ 1 0 0 0 0 0 0 ]
sub_caller main::foo 1 14 [ 1 0 0 0 0 0 0 ]
-sub_caller main::foo 2 1 [ 1 0 0 0 0 0 0 ]
+sub_caller main::foo 1 19 [ 1 0 0 0 0 0 0 ]
sub_subinfo main::bar [ 1 7 9 1 0 0 0 0 ]
sub_subinfo main::baz [ 1 11 17 1 0 0 0 0 ]
sub_subinfo main::foo [ 1 3 5 3 0 0 0 0 ]
Added: trunk/t/test20-streval.p
==============================================================================
--- (empty file)
+++ trunk/t/test20-streval.p Tue Oct 21 15:51:10 2008
@@ -0,0 +1,11 @@
+# test merging of sub calls from eval fids
+
+sub foo { print "foo\n" }
+
+my $code = 'foo()';
+
+# call once from particular line
+eval $code;
+
+# call twice from the same line
+eval $code or die $@ for (1,2);
Added: trunk/t/test20-streval.rdt
==============================================================================
--- (empty file)
+++ trunk/t/test20-streval.rdt Tue Oct 21 15:51:10 2008
@@ -0,0 +1,47 @@
+attribute application test20-streval.p
+attribute basetime 0
+attribute clock_id 0
+attribute nv_size 0
+attribute perl_version 0
+attribute profiler_duration 0
+attribute profiler_end_time 0
+attribute profiler_start_time 0
+attribute ticks_per_sec 0
+attribute total_stmts_discounted 0
+attribute total_stmts_duration 0
+attribute total_stmts_measured 0
+attribute xs_version 0
+fid_block_time 1 3 [ 0 3 ]
+fid_block_time 1 5 [ 0 1 ]
+fid_block_time 1 8 0 0
+fid_block_time 1 8 1 1
+fid_block_time 1 8 2 1 [ 0 1 ]
+fid_block_time 1 11 0 0
+fid_block_time 1 11 1 2
+fid_block_time 1 11 2 1 [ 0 2 ]
+fid_fileinfo 1 [ /.../test20-streval.p 1 2 0 0 ]
+fid_fileinfo 2 [ (eval 0)[test20-streval.p:8] 1 8 2 2 0 0 ]
+fid_fileinfo 3 [ (eval 0)[test20-streval.p:11] 1 11 3 2 0 0 ]
+fid_fileinfo 4 [ (eval 0)[test20-streval.p:11] 1 11 4 2 0 0 ]
+fid_line_time 1 3 [ 0 3 ]
+fid_line_time 1 5 [ 0 1 ]
+fid_line_time 1 8 0 0
+fid_line_time 1 8 1 1
+fid_line_time 1 8 2 1 [ 0 1 ]
+fid_line_time 1 11 0 0
+fid_line_time 1 11 1 2
+fid_line_time 1 11 2 1 [ 0 2 ]
+fid_sub_time 1 3 [ 0 3 ]
+fid_sub_time 1 5 [ 0 1 ]
+fid_sub_time 1 8 0 0
+fid_sub_time 1 8 1 1
+fid_sub_time 1 8 2 1 [ 0 1 ]
+fid_sub_time 1 11 0 0
+fid_sub_time 1 11 1 2
+fid_sub_time 1 11 2 1 [ 0 2 ]
+profile_modes fid_block_time block
+profile_modes fid_line_time line
+profile_modes fid_sub_time sub
+sub_caller main::foo 1 11 [ 2 0 0 0 0 0 0 ]
+sub_caller main::foo 1 8 [ 1 0 0 0 0 0 0 ]
+sub_subinfo main::foo [ 1 3 3 3 0 0 0 0 ]
--~--~---------~--~----~------------~-------~--~----~
You've received this message because you are subscribed to
the Devel::NYTProf Development User group.
Group hosted at: http://groups.google.com/group/develnytprof-dev
Project hosted at: http://perl-devel-nytprof.googlecode.com
CPAN distribution: http://search.cpan.org/dist/Devel-NYTProf
To post, email: [email protected]
To unsubscribe, email: [EMAIL PROTECTED]
-~----------~----~----~----~------~----~------~--~---