← Index
NYTProf Performance Profile   « line view »
For starman worker -M FindBin --max-requests 50 --workers 2 --user=kohadev-koha --group kohadev-koha --pid /var/run/koha/kohadev/plack.pid --daemonize --access-log /var/log/koha/kohadev/plack.log --error-log /var/log/koha/kohadev/plack-error.log -E deployment --socket /var/run/koha/kohadev/plack.sock /etc/koha/sites/kohadev/plack.psgi
  Run on Fri Jan 8 14:31:06 2016
Reported on Fri Jan 8 14:33:30 2016

Filename/usr/share/perl5/DBIx/Class/Storage/DBI/Cursor.pm
StatementsExecuted 34 statements in 178µs
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
222203µs33.5msDBIx::Class::Storage::DBI::Cursor::::nextDBIx::Class::Storage::DBI::Cursor::next
21138µs43µsDBIx::Class::Storage::DBI::Cursor::::newDBIx::Class::Storage::DBI::Cursor::new
21136µs155µsDBIx::Class::Storage::DBI::Cursor::::__finish_sthDBIx::Class::Storage::DBI::Cursor::__finish_sth
11135µs50µsDBIx::Class::Storage::DBI::Cursor::::BEGIN@10DBIx::Class::Storage::DBI::Cursor::BEGIN@10
42125µs25µsDBIx::Class::Storage::DBI::Cursor::::sthDBIx::Class::Storage::DBI::Cursor::sth
11121µs62µsDBIx::Class::Storage::DBI::Cursor::::BEGIN@8DBIx::Class::Storage::DBI::Cursor::BEGIN@8
11120µs31µsDBIx::Class::Storage::DBI::Cursor::::BEGIN@3DBIx::Class::Storage::DBI::Cursor::BEGIN@3
11119µs619µsDBIx::Class::Storage::DBI::Cursor::::BEGIN@6DBIx::Class::Storage::DBI::Cursor::BEGIN@6
22218µs172µsDBIx::Class::Storage::DBI::Cursor::::DESTROYDBIx::Class::Storage::DBI::Cursor::DESTROY
11115µs42µsDBIx::Class::Storage::DBI::Cursor::::BEGIN@9DBIx::Class::Storage::DBI::Cursor::BEGIN@9
11114µs199µsDBIx::Class::Storage::DBI::Cursor::::BEGIN@11DBIx::Class::Storage::DBI::Cursor::BEGIN@11
11112µs19µsDBIx::Class::Storage::DBI::Cursor::::BEGIN@4DBIx::Class::Storage::DBI::Cursor::BEGIN@4
0000s0sDBIx::Class::Storage::DBI::Cursor::::CLONEDBIx::Class::Storage::DBI::Cursor::CLONE
0000s0sDBIx::Class::Storage::DBI::Cursor::::__ANON__[:251]DBIx::Class::Storage::DBI::Cursor::__ANON__[:251]
0000s0sDBIx::Class::Storage::DBI::Cursor::::__ANON__[:252]DBIx::Class::Storage::DBI::Cursor::__ANON__[:252]
0000s0sDBIx::Class::Storage::DBI::Cursor::::allDBIx::Class::Storage::DBI::Cursor::all
0000s0sDBIx::Class::Storage::DBI::Cursor::::resetDBIx::Class::Storage::DBI::Cursor::reset
0000s0sDBIx::Class::Storage::DBI::Cursor::::try {...} DBIx::Class::Storage::DBI::Cursor::try {...}
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package DBIx::Class::Storage::DBI::Cursor;
2
3243µs
# spent 31µs (20+12) within DBIx::Class::Storage::DBI::Cursor::BEGIN@3 which was called: # once (20µs+12µs) by Class::C3::Componentised::ensure_class_loaded at line 3
use strict;
# spent 31µs making 1 call to DBIx::Class::Storage::DBI::Cursor::BEGIN@3 # spent 12µs making 1 call to strict::import
4226µs
# spent 19µs (12+7) within DBIx::Class::Storage::DBI::Cursor::BEGIN@4 which was called: # once (12µs+7µs) by Class::C3::Componentised::ensure_class_loaded at line 4
use warnings;
# spent 19µs making 1 call to DBIx::Class::Storage::DBI::Cursor::BEGIN@4 # spent 7µs making 1 call to warnings::import
5
621.22ms
# spent 619µs (19+601) within DBIx::Class::Storage::DBI::Cursor::BEGIN@6 which was called: # once (19µs+601µs) by Class::C3::Componentised::ensure_class_loaded at line 6
use base 'DBIx::Class::Cursor';
# spent 619µs making 1 call to DBIx::Class::Storage::DBI::Cursor::BEGIN@6 # spent 601µs making 1 call to base::import
7
82104µs
# spent 62µs (21+42) within DBIx::Class::Storage::DBI::Cursor::BEGIN@8 which was called: # once (21µs+42µs) by Class::C3::Componentised::ensure_class_loaded at line 8
use Try::Tiny;
# spent 62µs making 1 call to DBIx::Class::Storage::DBI::Cursor::BEGIN@8 # spent 42µs making 1 call to Exporter::import
9268µs
# spent 42µs (15+27) within DBIx::Class::Storage::DBI::Cursor::BEGIN@9 which was called: # once (15µs+27µs) by Class::C3::Componentised::ensure_class_loaded at line 9
use Scalar::Util qw(refaddr weaken);
# spent 42µs making 1 call to DBIx::Class::Storage::DBI::Cursor::BEGIN@9 # spent 27µs making 1 call to Exporter::import
10265µs
# spent 50µs (35+15) within DBIx::Class::Storage::DBI::Cursor::BEGIN@10 which was called: # once (35µs+15µs) by Class::C3::Componentised::ensure_class_loaded at line 10
use List::Util 'shuffle';
# spent 50µs making 1 call to DBIx::Class::Storage::DBI::Cursor::BEGIN@10 # spent 15µs making 1 call to List::Util::import
112383µs
# spent 199µs (14+185) within DBIx::Class::Storage::DBI::Cursor::BEGIN@11 which was called: # once (14µs+185µs) by Class::C3::Componentised::ensure_class_loaded at line 11
use namespace::clean;
# spent 199µs making 1 call to DBIx::Class::Storage::DBI::Cursor::BEGIN@11 # spent 185µs making 1 call to namespace::clean::import
12
131242µs__PACKAGE__->mk_group_accessors('simple' =>
# spent 242µs making 1 call to Class::Accessor::Grouped::mk_group_accessors
14 qw/storage args attrs/
15);
16
17=head1 NAME
18
19DBIx::Class::Storage::DBI::Cursor - Object representing a query cursor on a
20resultset.
21
22=head1 SYNOPSIS
23
24 my $cursor = $schema->resultset('CD')->cursor();
25
26 # raw values off the database handle in resultset columns/select order
27 my @next_cd_column_values = $cursor->next;
28
29 # list of all raw values as arrayrefs
30 my @all_cds_column_values = $cursor->all;
31
32=head1 DESCRIPTION
33
34A Cursor represents a query cursor on a L<DBIx::Class::ResultSet> object. It
35allows for traversing the result set with L</next>, retrieving all results with
36L</all> and resetting the cursor with L</reset>.
37
38Usually, you would use the cursor methods built into L<DBIx::Class::ResultSet>
39to traverse it. See L<DBIx::Class::ResultSet/next>,
40L<DBIx::Class::ResultSet/reset> and L<DBIx::Class::ResultSet/all> for more
41information.
42
43=head1 METHODS
44
45=head2 new
46
47Returns a new L<DBIx::Class::Storage::DBI::Cursor> object.
48
49=cut
50
51{
52 my %cursor_registry;
53
54
# spent 43µs (38+5) within DBIx::Class::Storage::DBI::Cursor::new which was called 2 times, avg 22µs/call: # 2 times (38µs+5µs) by DBIx::Class::Storage::DBI::select at line 2559 of DBIx/Class/Storage/DBI.pm, avg 22µs/call
sub new {
551700ns my ($class, $storage, $args, $attrs) = @_;
56
5714µs my $self = bless {
58 storage => $storage,
59 args => $args,
60 attrs => $attrs,
61 }, ref $class || $class;
62
631600ns if (DBIx::Class::_ENV_::HAS_ITHREADS) {
64
65 # quick "garbage collection" pass - prevents the registry
66 # from slowly growing with a bunch of undef-valued keys
67 defined $cursor_registry{$_} or delete $cursor_registry{$_}
6815µs for keys %cursor_registry;
69
70111µs45µs weaken( $cursor_registry{ refaddr($self) } = $self )
# spent 2µs making 2 calls to Scalar::Util::refaddr, avg 1µs/call # spent 2µs making 2 calls to Scalar::Util::weaken, avg 1µs/call
71 }
72
7313µs return $self;
74 }
75
76 sub CLONE {
77 for (keys %cursor_registry) {
78 # once marked we no longer care about them, hence no
79 # need to keep in the registry, left alone renumber the
80 # keys (all addresses are now different)
81 my $self = delete $cursor_registry{$_}
82 or next;
83
84 $self->{_intra_thread} = 1;
85 }
86 }
87}
88
89=head2 next
90
91=over 4
92
93=item Arguments: none
94
95=item Return Value: \@row_columns
96
97=back
98
99Advances the cursor to the next row and returns an array of column
100values (the result of L<DBI/fetchrow_array> method).
101
102=cut
103
104
# spent 33.5ms (203µs+33.3) within DBIx::Class::Storage::DBI::Cursor::next which was called 2 times, avg 16.7ms/call: # once (140µs+32.0ms) by DBIx::Class::ResultSet::_construct_results at line 1329 of DBIx/Class/ResultSet.pm # once (63µs+1.22ms) by DBIx::Class::ResultSetColumn::next at line 160 of DBIx/Class/ResultSetColumn.pm
sub next {
1051500ns my $self = shift;
106
10711µs return if $self->{_done};
108
1091100ns my $sth;
110
1111900ns if (
112 $self->{attrs}{software_limit}
113 && $self->{attrs}{rows}
114 && ($self->{_pos}||0) >= $self->{attrs}{rows}
115 ) {
116 if ($sth = $self->sth) {
117 # explicit finish will issue warnings, unlike the DESTROY below
118 $sth->finish if $sth->FETCH('Active');
119 }
120 $self->{_done} = 1;
121 return;
122 }
123
12415µs27µs unless ($sth = $self->sth) {
# spent 7µs making 2 calls to DBIx::Class::Storage::DBI::Cursor::sth, avg 3µs/call
125127µs432.3ms (undef, $sth, undef) = $self->storage->_select( @{$self->{args}} );
# spent 32.1ms making 2 calls to DBIx::Class::Storage::DBI::_select, avg 16.0ms/call # spent 179µs making 2 calls to DBIx::Class::Storage::DBI::Cursor::storage, avg 90µs/call
126
127114µs222µs $self->{_results} = [ (undef) x $sth->FETCH('NUM_OF_FIELDS') ];
# spent 22µs making 2 calls to DBI::common::FETCH, avg 11µs/call
12817µs41.83ms $sth->bind_columns( \( @{$self->{_results}} ) );
# spent 919µs making 2 calls to DBI::st::bind_columns, avg 459µs/call # spent 908µs making 2 calls to DBD::mysql::st::__ANON__[DBD/mysql.pm:810], avg 454µs/call
129
13011µs if ( $self->{attrs}{software_limit} and $self->{attrs}{offset} ) {
131 $sth->fetch for 1 .. $self->{attrs}{offset};
132 }
133
13412µs218µs $self->sth($sth);
# spent 18µs making 2 calls to DBIx::Class::Storage::DBI::Cursor::sth, avg 9µs/call
135 }
136
13718µs214µs if ($sth->fetch) {
# spent 14µs making 2 calls to DBI::st::fetch, avg 7µs/call
13811µs $self->{_pos}++;
13915µs return @{$self->{_results}};
140 } else {
141 $self->{_done} = 1;
142 return ();
143 }
144}
145
146
147=head2 all
148
149=over 4
150
151=item Arguments: none
152
153=item Return Value: \@row_columns+
154
155=back
156
157Returns a list of arrayrefs of column values for all rows in the
158L<DBIx::Class::ResultSet>.
159
160=cut
161
162sub all {
163 my $self = shift;
164
165 # delegate to DBIC::Cursor which will delegate back to next()
166 if ($self->{attrs}{software_limit}
167 && ($self->{attrs}{offset} || $self->{attrs}{rows})) {
168 return $self->next::method(@_);
169 }
170
171 my $sth;
172
173 if ($sth = $self->sth) {
174 # explicit finish will issue warnings, unlike the DESTROY below
175 $sth->finish if ( ! $self->{_done} and $sth->FETCH('Active') );
176 $self->sth(undef);
177 }
178
179 (undef, $sth) = $self->storage->_select( @{$self->{args}} );
180
181 return (
182 DBIx::Class::_ENV_::SHUFFLE_UNORDERED_RESULTSETS
183 and
184 ! $self->{attrs}{order_by}
185 )
186 ? shuffle @{$sth->fetchall_arrayref}
187 : @{$sth->fetchall_arrayref}
188 ;
189}
190
191
# spent 25µs within DBIx::Class::Storage::DBI::Cursor::sth which was called 4 times, avg 6µs/call: # 2 times (18µs+0s) by DBIx::Class::Storage::DBI::Cursor::next at line 134, avg 9µs/call # 2 times (7µs+0s) by DBIx::Class::Storage::DBI::Cursor::next at line 124, avg 3µs/call
sub sth {
1922600ns my $self = shift;
193
19422µs if (@_) {
19512µs delete @{$self}{qw/_pos _done _pid _intra_thread/};
196
19711µs $self->{sth} = $_[0];
19812µs $self->{_pid} = $$ if ! DBIx::Class::_ENV_::BROKEN_FORK and $_[0];
199 }
200 elsif ($self->{sth} and ! $self->{_done}) {
201
202 my $invalidate_handle_reason;
203
204 if (DBIx::Class::_ENV_::HAS_ITHREADS and $self->{_intra_thread} ) {
205 $invalidate_handle_reason = 'Multi-thread';
206 }
207 elsif (!DBIx::Class::_ENV_::BROKEN_FORK and $self->{_pid} != $$ ) {
208 $invalidate_handle_reason = 'Multi-process';
209 }
210
211 if ($invalidate_handle_reason) {
212 $self->storage->throw_exception("$invalidate_handle_reason access attempted while cursor in progress (position $self->{_pos})")
213 if $self->{_pos};
214
215 # reinvokes the reset logic above
216 $self->sth(undef);
217 }
218 }
219
22029µs return $self->{sth};
221}
222
223=head2 reset
224
225Resets the cursor to the beginning of the L<DBIx::Class::ResultSet>.
226
227=cut
228
229sub reset {
230 $_[0]->__finish_sth if $_[0]->{sth};
231 $_[0]->sth(undef);
232}
233
234
235
# spent 172µs (18+155) within DBIx::Class::Storage::DBI::Cursor::DESTROY which was called 2 times, avg 86µs/call: # once (10µs+103µs) by DBIx::Class::ResultSet::count at line 32 of Koha/Borrower/Discharge.pm # once (8µs+52µs) by CGI::Compile::ROOT::home_vagrant_kohaclone_circ_ysearch_2epl::__ANON__[/home/vagrant/kohaclone/circ/ysearch.pl:115] at line 2 of circ/ysearch.pl
sub DESTROY {
236110µs2155µs $_[0]->__finish_sth if $_[0]->{sth};
# spent 155µs making 2 calls to DBIx::Class::Storage::DBI::Cursor::__finish_sth, avg 78µs/call
237}
238
239
# spent 155µs (36+119) within DBIx::Class::Storage::DBI::Cursor::__finish_sth which was called 2 times, avg 78µs/call: # 2 times (36µs+119µs) by DBIx::Class::Storage::DBI::Cursor::DESTROY at line 236, avg 78µs/call
sub __finish_sth {
240 # It is (sadly) extremely important to finish() handles we are about
241 # to lose (due to reset() or a DESTROY() ). $rs->reset is the closest
242 # thing the user has to getting to the underlying finish() API and some
243 # DBDs mandate this (e.g. DBD::InterBase will segfault, DBD::Sybase
244 # won't start a transaction sanely, etc)
245 # We also can't use the accessor here, as it will trigger a fork/thread
246 # check, and resetting a cursor in a child is perfectly valid
247
2481500ns my $self = shift;
249
250 # No need to care about failures here
251220µs13µs try { local $SIG{__WARN__} = sub {}; $self->{sth}->finish } if (
# spent 3µs making 1 call to DBI::st::finish
25218µs27µs $self->{sth} and ! try { ! $self->{sth}->FETCH('Active') }
# spent 7µs making 2 calls to DBI::common::FETCH, avg 4µs/call
253126µs3119µs );
# spent 119µs making 3 calls to Try::Tiny::try, avg 40µs/call
254}
255
256=head1 FURTHER QUESTIONS?
257
258Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
259
260=head1 COPYRIGHT AND LICENSE
261
262This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
263by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
264redistribute it and/or modify it under the same terms as the
265L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
266
267=cut
268
2691179µs1;
# spent 179µs making 1 call to B::Hooks::EndOfScope::XS::__ANON__