Profile of DBIx/Class/Storage/TxnScopeGuard.pm

← Index
NYTProf Performance Profile «block view•line view•sub view»
For xt/tapper-mcp-scheduler-with-db-longrun.t
Run on Tue May 22 17:18:39 2012
Reported on Tue May 22 17:23:15 2012

Filename | /2home/ss5/perl5/perlbrew/perls/perl-5.12.3/lib/site_perl/5.12.3/DBIx/Class/Storage/TxnScopeGuard.pm
Statements | Executed 5318 statements in 18.1ms

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
294 | 1 | 1 | 8.91ms | 71.5ms | DBIx::Class::Storage::TxnScopeGuard::::newDBIx::Class::Storage::TxnScopeGuard::new
294 | 2 | 2 | 4.88ms | 4.88ms | DBIx::Class::Storage::TxnScopeGuard::::DESTROYDBIx::Class::Storage::TxnScopeGuard::DESTROY
294 | 2 | 2 | 4.65ms | 34.9s | DBIx::Class::Storage::TxnScopeGuard::::commitDBIx::Class::Storage::TxnScopeGuard::commit
1 | 1 | 1 | 16µs | 16µs | DBIx::Class::Storage::TxnScopeGuard::::BEGIN@7DBIx::Class::Storage::TxnScopeGuard::BEGIN@7
1 | 1 | 1 | 12µs | 14µs | DBIx::Class::Storage::TxnScopeGuard::::BEGIN@3DBIx::Class::Storage::TxnScopeGuard::BEGIN@3
1 | 1 | 1 | 10µs | 46µs | DBIx::Class::Storage::TxnScopeGuard::::BEGIN@5DBIx::Class::Storage::TxnScopeGuard::BEGIN@5
1 | 1 | 1 | 7µs | 34µs | DBIx::Class::Storage::TxnScopeGuard::::BEGIN@6DBIx::Class::Storage::TxnScopeGuard::BEGIN@6
1 | 1 | 1 | 7µs | 238µs | DBIx::Class::Storage::TxnScopeGuard::::BEGIN@10DBIx::Class::Storage::TxnScopeGuard::BEGIN@10
1 | 1 | 1 | 7µs | 15µs | DBIx::Class::Storage::TxnScopeGuard::::BEGIN@4DBIx::Class::Storage::TxnScopeGuard::BEGIN@4
1 | 1 | 1 | 6µs | 6µs | DBIx::Class::Storage::TxnScopeGuard::::BEGIN@8DBIx::Class::Storage::TxnScopeGuard::BEGIN@8
1 | 1 | 1 | 6µs | 56µs | DBIx::Class::Storage::TxnScopeGuard::::BEGIN@9DBIx::Class::Storage::TxnScopeGuard::BEGIN@9
0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::TxnScopeGuard::::__ANON__[:138]DBIx::Class::Storage::TxnScopeGuard::__ANON__[:138]
0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::TxnScopeGuard::::__ANON__[:139]DBIx::Class::Storage::TxnScopeGuard::__ANON__[:139]
0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::TxnScopeGuard::::__ANON__[:51]DBIx::Class::Storage::TxnScopeGuard::__ANON__[:51]
0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::TxnScopeGuard::::__ANON__[:61]DBIx::Class::Storage::TxnScopeGuard::__ANON__[:61]

Call graph for these subroutines as a Graphviz dot language file.

Line | State ments | Time on line | Calls | Time in subs | Code
--- | --- | --- | --- | --- | ---
1 |  |  |  |  | package DBIx::Class::Storage::TxnScopeGuard;
2 |  |  |  |  |
3 | 3 | 17µs | 2 | 16µs | # spent 14µs (12+2) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@3 which was called: # once (12µs+2µs) by DBIx::Class::Storage::BEGIN@17 at line 3 use strict; # spent 14µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@3 # spent 2µs making 1 call to strict::import
4 | 3 | 20µs | 2 | 24µs | # spent 15µs (7+9) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@4 which was called: # once (7µs+9µs) by DBIx::Class::Storage::BEGIN@17 at line 4 use warnings; # spent 15µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@4 # spent 9µs making 1 call to warnings::import
5 | 3 | 23µs | 2 | 81µs | # spent 46µs (10+36) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@5 which was called: # once (10µs+36µs) by DBIx::Class::Storage::BEGIN@17 at line 5 use Try::Tiny; # spent 46µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@5 # spent 36µs making 1 call to Exporter::import
6 | 3 | 26µs | 2 | 60µs | # spent 34µs (7+27) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@6 which was called: # once (7µs+27µs) by DBIx::Class::Storage::BEGIN@17 at line 6 use Scalar::Util qw/weaken blessed refaddr/; # spent 34µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@6 # spent 27µs making 1 call to Exporter::import
7 | 3 | 29µs | 1 | 16µs | # spent 16µs within DBIx::Class::Storage::TxnScopeGuard::BEGIN@7 which was called: # once (16µs+0s) by DBIx::Class::Storage::BEGIN@17 at line 7 use DBIx::Class; # spent 16µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@7
8 | 3 | 18µs | 1 | 6µs | # spent 6µs within DBIx::Class::Storage::TxnScopeGuard::BEGIN@8 which was called: # once (6µs+0s) by DBIx::Class::Storage::BEGIN@17 at line 8 use DBIx::Class::Exception; # spent 6µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@8
9 | 3 | 17µs | 2 | 107µs | # spent 56µs (6+50) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@9 which was called: # once (6µs+50µs) by DBIx::Class::Storage::BEGIN@17 at line 9 use DBIx::Class::Carp; # spent 56µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@9 # spent 50µs making 1 call to DBIx::Class::Carp::import
10 | 3 | 575µs | 2 | 469µs | # spent 238µs (7+231) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@10 which was called: # once (7µs+231µs) by DBIx::Class::Storage::BEGIN@17 at line 10 use namespace::clean; # spent 238µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@10 # spent 231µs making 1 call to namespace::clean::import
11 |  |  |  |  |
12 | 1 | 300ns |  |  | my ($guards_count, $compat_handler, $foreign_handler);
13 |  |  |  |  |
14 |  |  |  |  | # spent 71.5ms (8.91+62.6) within DBIx::Class::Storage::TxnScopeGuard::new which was called 294 times, avg 243µs/call: # 294 times (8.91ms+62.6ms) by DBIx::Class::Storage::txn_scope_guard at line 488 of DBIx/Class/Storage.pm, avg 243µs/call sub new {
15 | 2940 | 8.38ms |  |  | my ($class, $storage) = @_;
16 |  |  |  |  |
17 |  |  |  |  | my $guard = {
18 |  |  |  |  | inactivated => 0,
19 |  |  |  |  | storage => $storage,
20 |  |  |  |  | };
21 |  |  |  |  |
22 |  |  |  |  | # we are starting with an already set $@ - in order for things to work we need to
23 |  |  |  |  | # be able to recognize it upon destruction - store its weakref
24 |  |  |  |  | # recording it before doing the txn_begin stuff
25 |  |  |  |  | if (defined $@ and $@ ne '') {
26 |  |  |  |  | $guard->{existing_exception_ref} = (ref $@ ne '') ? $@ : \$@;
27 |  |  |  |  | weaken $guard->{existing_exception_ref};
28 |  |  |  |  | }
29 |  |  |  |  |
30 |  |  | 294 | 2.24ms | $storage->txn_begin; # spent 2.24ms making 294 calls to DBIx::Class::Storage::DBI::txn_begin, avg 8µs/call
31 |  |  |  |  |
32 |  |  | 1 | 1µs | $guard->{dbh} = $storage->_dbh; # spent 1µs making 1 call to DBIx::Class::Storage::DBI::_dbh
33 |  |  | 294 | 832µs | weaken $guard->{dbh}; # spent 832µs making 294 calls to Scalar::Util::weaken, avg 3µs/call
34 |  |  |  |  |
35 |  |  |  |  | bless $guard, ref $class || $class;
36 |  |  |  |  |
37 |  |  |  |  | # install a callback carefully
38 |  |  |  |  | if (DBIx::Class::_ENV_::INVISIBLE_DOLLAR_AT and !$guards_count) {
39 |  |  |  |  |
40 |  |  |  |  | # if the thrown exception is a plain string, wrap it in our
41 |  |  |  |  | # own exception class
42 |  |  |  |  | # this is actually a pretty cool idea, may very well keep it
43 |  |  |  |  | # after perl is fixed
44 |  |  |  |  | $compat_handler ||= bless(
45 |  |  |  |  | sub {
46 |  |  |  |  | $@ = (blessed($_[0]) or ref($_[0]))
47 |  |  |  |  | ? $_[0]
48 |  |  |  |  | : bless ( { msg => $_[0] }, 'DBIx::Class::Exception')
49 |  |  |  |  | ;
50 |  |  |  |  | die;
51 |  |  |  |  | },
52 |  |  |  |  | '__TxnScopeGuard__FIXUP__',
53 |  |  |  |  | );
54 |  |  |  |  |
55 |  |  |  |  | if ($foreign_handler = $SIG{__DIE__}) {
56 |  |  |  |  | $SIG{__DIE__} = bless (
57 |  |  |  |  | sub {
58 |  |  |  |  | # we trust the foreign handler to do whatever it wants, all we do is set $@
59 |  |  |  |  | eval { $compat_handler->(@_) };
60 |  |  |  |  | $foreign_handler->(@_);
61 |  |  |  |  | },
62 |  |  |  |  | '__TxnScopeGuard__FIXUP__',
63 |  |  |  |  | );
64 |  |  |  |  | }
65 |  |  |  |  | else {
66 |  |  |  |  | $SIG{__DIE__} = $compat_handler;
67 |  |  |  |  | }
68 |  |  |  |  | }
69 |  |  |  |  |
70 |  |  |  |  | $guards_count++;
71 |  |  |  |  |
72 |  |  |  |  | $guard;
73 |  |  |  |  | }
74 |  |  |  |  |
75 |  |  |  |  | # spent 34.9s (4.65ms+34.9) within DBIx::Class::Storage::TxnScopeGuard::commit which was called 294 times, avg 119ms/call: # 147 times (2.40ms+17.7s) by DBIx::Class::Relationship::CascadeActions::update at line 70 of DBIx/Class/Relationship/CascadeActions.pm, avg 120ms/call # 147 times (2.25ms+17.2s) by DBIx::Class::Row::insert at line 405 of DBIx/Class/Row.pm, avg 117ms/call sub commit {
76 | 1176 | 4.85ms |  |  | my $self = shift;
77 |  |  |  |  |
78 |  |  |  |  | $self->{storage}->throw_exception("Refusing to execute multiple commits on scope guard $self")
79 |  |  |  |  | if $self->{inactivated};
80 |  |  |  |  |
81 |  |  | 294 | 34.9s | $self->{storage}->txn_commit; # spent 34.9s making 294 calls to DBIx::Class::Storage::DBI::txn_commit, avg 119ms/call
82 |  |  |  |  | $self->{inactivated} = 1;
83 |  |  |  |  | }
84 |  |  |  |  |
85 |  |  |  |  | # spent 4.88ms within DBIx::Class::Storage::TxnScopeGuard::DESTROY which was called 294 times, avg 17µs/call: # 147 times (2.44ms+0s) by DBIx::Class::Relationship::CascadeActions::update at line 136 of lib/Tapper/MCP/Scheduler/Controller.pm, avg 17µs/call # 147 times (2.44ms+0s) by DBIx::Class::Row::insert at line 150 of Tapper/Schema/TestrunDB/Result/Testrun.pm, avg 17µs/call sub DESTROY {
86 | 1176 | 4.12ms |  |  | my $self = shift;
87 |  |  |  |  |
88 |  |  |  |  | $guards_count--;
89 |  |  |  |  |
90 |  |  |  |  | # don't touch unless it's ours, and there are no more of us left
91 |  |  |  |  | if (
92 |  |  |  |  | DBIx::Class::_ENV_::INVISIBLE_DOLLAR_AT
93 |  |  |  |  | and
94 |  |  |  |  | !$guards_count
95 |  |  |  |  | ) {
96 |  |  |  |  |
97 |  |  |  |  | if (ref $SIG{__DIE__} eq '__TxnScopeGuard__FIXUP__') {
98 |  |  |  |  | # restore what we saved
99 |  |  |  |  | if ($foreign_handler) {
100 |  |  |  |  | $SIG{__DIE__} = $foreign_handler;
101 |  |  |  |  | }
102 |  |  |  |  | else {
103 |  |  |  |  | delete $SIG{__DIE__};
104 |  |  |  |  | }
105 |  |  |  |  | }
106 |  |  |  |  |
107 |  |  |  |  | # make sure we do not leak the foreign one in case it exists
108 |  |  |  |  | undef $foreign_handler;
109 |  |  |  |  | }
110 |  |  |  |  |
111 |  |  |  |  | return if $self->{inactivated};
112 |  |  |  |  |
113 |  |  |  |  | # if our dbh is not ours anymore, the $dbh weakref will go undef
114 |  |  |  |  | $self->{storage}->_verify_pid;
115 |  |  |  |  | return unless $self->{dbh};
116 |  |  |  |  |
117 |  |  |  |  | my $exception = $@ if (
118 |  |  |  |  | defined $@
119 |  |  |  |  | and
120 |  |  |  |  | $@ ne ''
121 |  |  |  |  | and
122 |  |  |  |  | (
123 |  |  |  |  | ! defined $self->{existing_exception_ref}
124 |  |  |  |  | or
125 |  |  |  |  | refaddr( ref $@ eq '' ? \$@ : $@ ) != refaddr($self->{existing_exception_ref})
126 |  |  |  |  | )
127 |  |  |  |  | );
128 |  |  |  |  |
129 |  |  |  |  | {
130 |  |  |  |  | local $@;
131 |  |  |  |  |
132 |  |  |  |  | carp 'A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or error. Rolling back.'
133 |  |  |  |  | unless defined $exception;
134 |  |  |  |  |
135 |  |  |  |  | my $rollback_exception;
136 |  |  |  |  | # do minimal connectivity check due to weird shit like
137 |  |  |  |  | # https://rt.cpan.org/Public/Bug/Display.html?id=62370
138 |  |  |  |  | try { $self->{storage}->_seems_connected && $self->{storage}->txn_rollback }
139 |  |  |  |  | catch { $rollback_exception = shift };
140 |  |  |  |  |
141 |  |  |  |  | if ( $rollback_exception and (
142 |  |  |  |  | ! defined blessed $rollback_exception
143 |  |  |  |  | or
144 |  |  |  |  | ! $rollback_exception->isa('DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION')
145 |  |  |  |  | ) ) {
146 |  |  |  |  | # append our text - THIS IS A TEMPORARY FIXUP!
147 |  |  |  |  | # a real stackable exception object is in the works
148 |  |  |  |  | if (ref $exception eq 'DBIx::Class::Exception') {
149 |  |  |  |  | $exception->{msg} = "Transaction aborted: $exception->{msg} "
150 |  |  |  |  | ."Rollback failed: ${rollback_exception}";
151 |  |  |  |  | }
152 |  |  |  |  | elsif ($exception) {
153 |  |  |  |  | $exception = "Transaction aborted: ${exception} "
154 |  |  |  |  | ."Rollback failed: ${rollback_exception}";
155 |  |  |  |  | }
156 |  |  |  |  | else {
157 |  |  |  |  | carp (join ' ',
158 |  |  |  |  | "********************* ROLLBACK FAILED!!! ********************",
159 |  |  |  |  | "\nA rollback operation failed after the guard went out of scope.",
160 |  |  |  |  | 'This is potentially a disastrous situation, check your data for',
161 |  |  |  |  | "consistency: $rollback_exception"
162 |  |  |  |  | );
163 |  |  |  |  | }
164 |  |  |  |  | }
165 |  |  |  |  | }
166 |  |  |  |  |
167 |  |  |  |  | $@ = $exception unless DBIx::Class::_ENV_::INVISIBLE_DOLLAR_AT;
168 |  |  |  |  | }
169 |  |  |  |  |
170 | 1 | 3µs |  |  | 1;
171 |  |  |  |  |
172 | 1 | 7µs | 1 | 561µs | __END__ # spent 561µs making 1 call to B::Hooks::EndOfScope::__ANON__[B/Hooks/EndOfScope.pm:26]