comparison Lib/IMPL/Profiler.pm @ 134:44977efed303

Significant performance optimizations Fixed recursion problems due converting objects to JSON Added cache support for the templates Added discovery feature for the web methods
author wizard
date Mon, 21 Jun 2010 02:39:53 +0400
parents 16ada169ca75
children 4d0e1962161c
comparison
equal deleted inserted replaced
133:a07a66fd8d5c 134:44977efed303
1 package IMPL::Profiler; 1 package IMPL::Profiler;
2
3 use strict;
4 use warnings;
5 use Time::HiRes;
6 require Scalar::Util;
2 7
3 our $Enabled; 8 our $Enabled;
4 our %TrappedModules; 9 our %TrappedModules;
5 our %InvokeInfo; 10 our %InvokeInfo;
6 our $InvokeTime = 0; 11 our $InvokeTime = 0;
12 our @TrapQueue;
13 our $Filter ||= qr//;
7 my $level; 14 my $level;
8 15
9 BEGIN { 16 BEGIN {
10 $level = 0; 17 $level = 0;
11 if ($Enabled) { 18 if ($Enabled) {
12 warn "profiler enabled"; 19 warn "profiler enabled";
20
21 unshift @INC, sub {
22 my ($self,$filename) = @_;
23
24 (my $module = $filename) =~ s/\//::/g;
25 $module =~ s/\.\w+$//;
26
27 return unless $module =~ $Filter;
28
29 foreach my $dir (@INC) {
30 my $fullName = "$dir/$filename";
31 if (-f $fullName) {
32 open my $hmod, $fullName or die "$fullName: $!" if $!;
33
34
35
36 my @source;
37 local $/ = "\n";
38 while (my $line = <$hmod>) {
39 last if $line =~ /^\s*__END__/;
40 push @source, $line;
41 }
42
43 undef $hmod;
44
45 push @source,
46 "IMPL::Profiler::trap_all(__PACKAGE__);\n",
47 "1;\n";
48
49
50 return (sub {
51 if (@source) {
52 $_ = shift @source;
53 return 1;
54 } else {
55 return 0;
56 }
57 }, undef );
58 }
59 }
60 };
61
13 no warnings 'once'; 62 no warnings 'once';
14 *CORE::GLOBAL::caller = sub { 63 *CORE::GLOBAL::caller = sub {
15 my $target = (shift || 0)+1; 64 my $target = (shift || 0)+1;
16 my $realFrame = 1; 65 my $realFrame = 1;
17 66
30 #warn "\t"x$level,"$frame[0] - $frame[3]"; 79 #warn "\t"x$level,"$frame[0] - $frame[3]";
31 return wantarray ? @frame : $frame[0]; 80 return wantarray ? @frame : $frame[0];
32 }; 81 };
33 } 82 }
34 } 83 }
35 use strict;
36 use warnings;
37 use Time::HiRes;
38 require Scalar::Util;
39
40
41 84
42 sub trap_all { 85 sub trap_all {
43 return if not $Enabled; 86 return if not $Enabled;
44 no strict 'refs'; 87 no strict 'refs';
45 foreach my $class (@_) { 88 foreach my $class (@_) {
49 eval "warn 'load $class'; require $class;" if not %{"${class}::"}; 92 eval "warn 'load $class'; require $class;" if not %{"${class}::"};
50 die $@ if $@; 93 die $@ if $@;
51 94
52 no strict 'refs'; 95 no strict 'refs';
53 my $table = \%{"${class}::"}; 96 my $table = \%{"${class}::"};
54 trap($class,$_) foreach (grep *{$table->{$_}}{CODE}, keys %$table); 97 trap($class,$_) foreach (grep eval { *{$table->{$_}}{CODE} }, keys %$table); # here can be a not a GLOB reference
55 } 98 }
56 } 99 }
57 100
58 sub trap { 101 sub trap {
59 my ($class,$method) = @_; 102 my ($class,$method) = @_;
60 103
61 return if not $Enabled; 104 return if not $Enabled;
105
106 return if $method eq 'import';
62 107
63 no strict 'refs'; 108 no strict 'refs';
64 my $prevCode = \&{"${class}::${method}"}; 109 my $prevCode = \&{"${class}::${method}"};
65 my $proto = prototype $prevCode; 110 my $proto = prototype $prevCode;
66 111
67 if (defined $proto and not $proto) { 112 if (defined $proto and not $proto) {
68 return; 113 return;
69 } 114 }
70 { 115 {
71 package IMPL::Profiler::Proxy; 116 package IMPL::Profiler::Proxy;
72 no warnings 'redefine'; 117 no warnings 'redefine';
73 my $sub = sub { 118 my $sub = sub {
74 my $t0 = [Time::HiRes::gettimeofday]; 119 my $t0 = [Time::HiRes::gettimeofday];
75 my @arr; 120 my @arr;
76 my $scalar; 121 my $scalar;
77 my $entry = $prevCode; 122 my $entry = $prevCode;
78 my ($timeOwn,$timeTotal); 123 my ($timeOwn,$timeTotal);
79 my $context = wantarray; 124 my $context = wantarray;
80 { 125 {
81 local $InvokeTime = 0; 126 local $InvokeTime = 0;
82 #warn "\t"x$level,"enter ${class}::$method"; 127 #warn "\t"x$level,"enter ${class}::$method";
83 $level ++; 128 $level ++;
84 if ($context) { 129 if ($context) {
85 @arr = &$entry(@_); 130 @arr = &$entry(@_);
86 } else { 131 } else {
87 if (defined $context) { 132 if (defined $context) {
88 $scalar = &$entry(@_); 133 $scalar = &$entry(@_);
89 } else { 134 } else {
90 &$entry(@_); 135 &$entry(@_);
91 } 136 }
92 } 137 }
93 $timeTotal = Time::HiRes::tv_interval($t0); 138 $timeTotal = Time::HiRes::tv_interval($t0);
94 $timeOwn = $timeTotal - $InvokeTime; 139 $timeOwn = $timeTotal - $InvokeTime;
95 } 140 }
96 $InvokeInfo{"${class}::${method}"}{Count} ++; 141 $InvokeInfo{"${class}::${method}"}{Count} ++;
97 $InvokeInfo{"${class}::${method}"}{Total} += $timeTotal; 142 $InvokeInfo{"${class}::${method}"}{Total} += $timeTotal;
98 $InvokeInfo{"${class}::${method}"}{Own} += $timeOwn; 143 $InvokeInfo{"${class}::${method}"}{Own} += $timeOwn;
99 $InvokeTime += $timeTotal; 144 $InvokeTime += $timeTotal;
100 $level --; 145 $level --;
101 #warn "\t"x$level,"leave ${class}::$method"; 146 #warn "\t"x$level,"leave ${class}::$method";
102 return $context ? @arr : $scalar; 147 return $context ? @arr : $scalar;
103 }; 148 };
104 if ($proto) { 149 if ($proto) {
105 Scalar::Util::set_prototype($sub => $proto); 150 Scalar::Util::set_prototype($sub => $proto);
106 } 151 }
107 *{"${class}::${method}"} = $sub; 152 *{"${class}::${method}"} = $sub;
108 } 153 }
109 154
110 } 155 }
111 156
112 sub PrintStatistics { 157 sub PrintStatistics {