← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/share/koha/opac/cgi-bin/opac/opac-search.pl
  Run on Tue Oct 15 11:58:52 2013
Reported on Tue Oct 15 12:01:27 2013

Filename/usr/share/perl5/MARC/File/USMARC.pm
StatementsExecuted 15667 statements in 47.1ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
251142.8ms138msMARC::File::USMARC::::decodeMARC::File::USMARC::decode
1707613.15ms3.15msMARC::File::USMARC::::CORE:matchMARC::File::USMARC::CORE:match (opcode)
544111.53ms1.53msMARC::File::USMARC::::CORE:unpackMARC::File::USMARC::CORE:unpack (opcode)
111926µs1.09msMARC::File::USMARC::::BEGIN@15MARC::File::USMARC::BEGIN@15
111287µs9.53msMARC::File::USMARC::::BEGIN@13MARC::File::USMARC::BEGIN@13
11119µs24µsMARC::File::USMARC::::BEGIN@9MARC::File::USMARC::BEGIN@9
11115µs75µsMARC::File::USMARC::::BEGIN@20MARC::File::USMARC::BEGIN@20
11113µs16µsMARC::File::USMARC::::BEGIN@10MARC::File::USMARC::BEGIN@10
11113µs42µsMARC::File::USMARC::::BEGIN@16MARC::File::USMARC::BEGIN@16
11112µs57µsMARC::File::USMARC::::BEGIN@18MARC::File::USMARC::BEGIN@18
11111µs44µsMARC::File::USMARC::::BEGIN@22MARC::File::USMARC::BEGIN@22
1119µs45µsMARC::File::USMARC::::BEGIN@21MARC::File::USMARC::BEGIN@21
1119µs39µsMARC::File::USMARC::::BEGIN@12MARC::File::USMARC::BEGIN@12
1119µs9µsMARC::File::USMARC::::BEGIN@19MARC::File::USMARC::BEGIN@19
1119µs40µsMARC::File::USMARC::::BEGIN@23MARC::File::USMARC::BEGIN@23
0000s0sMARC::File::USMARC::::_build_tag_directoryMARC::File::USMARC::_build_tag_directory
0000s0sMARC::File::USMARC::::_nextMARC::File::USMARC::_next
0000s0sMARC::File::USMARC::::encodeMARC::File::USMARC::encode
0000s0sMARC::File::USMARC::::update_leaderMARC::File::USMARC::update_leader
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package MARC::File::USMARC;
2
3=head1 NAME
4
- -
9336µs229µs
# spent 24µs (19+5) within MARC::File::USMARC::BEGIN@9 which was called: # once (19µs+5µs) by C4::Biblio::BEGIN@28 at line 9
use strict;
# spent 24µs making 1 call to MARC::File::USMARC::BEGIN@9 # spent 5µs making 1 call to strict::import
10331µs220µs
# spent 16µs (13+4) within MARC::File::USMARC::BEGIN@10 which was called: # once (13µs+4µs) by C4::Biblio::BEGIN@28 at line 10
use integer;
# spent 16µs making 1 call to MARC::File::USMARC::BEGIN@10 # spent 4µs making 1 call to integer::import
11
12332µs269µs
# spent 39µs (9+30) within MARC::File::USMARC::BEGIN@12 which was called: # once (9µs+30µs) by C4::Biblio::BEGIN@28 at line 12
use vars qw( $ERROR );
# spent 39µs making 1 call to MARC::File::USMARC::BEGIN@12 # spent 30µs making 1 call to vars::import
133161µs29.61ms
# spent 9.53ms (287µs+9.24) within MARC::File::USMARC::BEGIN@13 which was called: # once (287µs+9.24ms) by C4::Biblio::BEGIN@28 at line 13
use MARC::File::Encode qw( marc_to_utf8 );
# spent 9.53ms making 1 call to MARC::File::USMARC::BEGIN@13 # spent 85µs making 1 call to Exporter::import
14
153150µs11.09ms
# spent 1.09ms (926µs+160µs) within MARC::File::USMARC::BEGIN@15 which was called: # once (926µs+160µs) by C4::Biblio::BEGIN@28 at line 15
use MARC::File;
# spent 1.09ms making 1 call to MARC::File::USMARC::BEGIN@15
16459µs272µs
# spent 42µs (13+30) within MARC::File::USMARC::BEGIN@16 which was called: # once (13µs+30µs) by C4::Biblio::BEGIN@28 at line 16
use vars qw( @ISA ); @ISA = qw( MARC::File );
# spent 42µs making 1 call to MARC::File::USMARC::BEGIN@16 # spent 30µs making 1 call to vars::import
17
18334µs2102µs
# spent 57µs (12+45) within MARC::File::USMARC::BEGIN@18 which was called: # once (12µs+45µs) by C4::Biblio::BEGIN@28 at line 18
use MARC::Record qw( LEADER_LEN );
# spent 57µs making 1 call to MARC::File::USMARC::BEGIN@18 # spent 45µs making 1 call to Exporter::import
19337µs19µs
# spent 9µs within MARC::File::USMARC::BEGIN@19 which was called: # once (9µs+0s) by C4::Biblio::BEGIN@28 at line 19
use MARC::Field;
# spent 9µs making 1 call to MARC::File::USMARC::BEGIN@19
20344µs2135µs
# spent 75µs (15+60) within MARC::File::USMARC::BEGIN@20 which was called: # once (15µs+60µs) by C4::Biblio::BEGIN@28 at line 20
use constant SUBFIELD_INDICATOR => "\x1F";
# spent 75µs making 1 call to MARC::File::USMARC::BEGIN@20 # spent 60µs making 1 call to constant::import
21337µs280µs
# spent 45µs (9+35) within MARC::File::USMARC::BEGIN@21 which was called: # once (9µs+35µs) by C4::Biblio::BEGIN@28 at line 21
use constant END_OF_FIELD => "\x1E";
# spent 45µs making 1 call to MARC::File::USMARC::BEGIN@21 # spent 35µs making 1 call to constant::import
22332µs278µs
# spent 44µs (11+34) within MARC::File::USMARC::BEGIN@22 which was called: # once (11µs+34µs) by C4::Biblio::BEGIN@28 at line 22
use constant END_OF_RECORD => "\x1D";
# spent 44µs making 1 call to MARC::File::USMARC::BEGIN@22 # spent 34µs making 1 call to constant::import
2331.19ms272µs
# spent 40µs (9+31) within MARC::File::USMARC::BEGIN@23 which was called: # once (9µs+31µs) by C4::Biblio::BEGIN@28 at line 23
use constant DIRECTORY_ENTRY_LEN => 12;
# spent 40µs making 1 call to MARC::File::USMARC::BEGIN@23 # spent 31µs making 1 call to constant::import
24
25=head1 SYNOPSIS
26
- -
45sub _next {
46 my $self = shift;
47 my $fh = $self->{fh};
48
49 my $reclen;
50 return if eof($fh);
51
52 local $/ = END_OF_RECORD;
53 my $usmarc = <$fh>;
54
55 # remove illegal garbage that sometimes occurs between records
56 $usmarc =~ s/^[ \x00\x0a\x0d\x1a]+//;
57
58 return $usmarc;
59}
60
61=head2 decode( $string [, \&filter_func ] )
62
- -
97
# spent 138ms (42.8+95.1) within MARC::File::USMARC::decode which was called 25 times, avg 5.51ms/call: # 25 times (42.8ms+95.1ms) by C4::Search::searchResults at line 1701 of /usr/share/koha/lib/C4/Search.pm, avg 5.51ms/call
sub decode {
98
995002.91ms my $text;
100 my $location = '';
101
102 ## decode can be called in a variety of ways
103 ## $object->decode( $string )
104 ## MARC::File::USMARC->decode( $string )
105 ## MARC::File::USMARC::decode( $string )
106 ## this bit of code covers all three
107
108 my $self = shift;
10950650µs25100µs if ( ref($self) =~ /^MARC::File/ ) {
# spent 100µs making 25 calls to MARC::File::USMARC::CORE:match, avg 4µs/call
110 $location = 'in record '.$self->{recnum};
111 $text = shift;
112 } else {
113 $location = 'in record 1';
1142580µs $text = $self=~/MARC::File/ ? shift : $self;
# spent 80µs making 25 calls to MARC::File::USMARC::CORE:match, avg 3µs/call
115 }
116 my $filter_func = shift;
117
118 # ok this the empty shell we will fill
11925569µs my $marc = MARC::Record->new();
# spent 569µs making 25 calls to MARC::Record::new, avg 23µs/call
120
121 # Check for an all-numeric record length
12225255µs ($text =~ /^(\d{5})/)
# spent 255µs making 25 calls to MARC::File::USMARC::CORE:match, avg 10µs/call
123 or return $marc->_warn( "Record length \"", substr( $text, 0, 5 ), "\" is not numeric $location" );
124
125 my $reclen = $1;
12625831µs my $realLength = bytes::length( $text );
# spent 658µs making 1 call to bytes::AUTOLOAD # spent 174µs making 24 calls to bytes::length, avg 7µs/call
127 $marc->_warn( "Invalid record length $location: Leader says $reclen " .
128 "bytes but it's actually $realLength" ) unless $reclen == $realLength;
129
130 (substr($text, -1, 1) eq END_OF_RECORD)
131 or $marc->_warn( "Invalid record terminator $location" );
132
13325370µs $marc->leader( substr( $text, 0, LEADER_LEN ) );
# spent 370µs making 25 calls to MARC::Record::leader, avg 15µs/call
134
135 # bytes 12 - 16 of leader give offset to the body of the record
13625187µs my $data_start = 0 + bytes::substr( $text, 12, 5 );
# spent 187µs making 25 calls to bytes::substr, avg 7µs/call
137
138 # immediately after the leader comes the directory (no separator)
139 my $dir = substr( $text, LEADER_LEN, $data_start - LEADER_LEN - 1 ); # -1 to allow for \x1e at end of directory
140
141 # character after the directory must be \x1e
142 (substr($text, $data_start-1, 1) eq END_OF_FIELD)
143 or $marc->_warn( "No directory found $location" );
144
145 # all directory entries 12 bytes long, so length % 12 must be 0
146 (length($dir) % DIRECTORY_ENTRY_LEN == 0)
147 or $marc->_warn( "Invalid directory length $location" );
148
149
150 # go through all the fields
151 my $nfields = length($dir)/DIRECTORY_ENTRY_LEN;
152652823.6ms for ( my $n = 0; $n < $nfields; $n++ ) {
1535441.53ms my ( $tagno, $len, $offset ) = unpack( "A3 A4 A5", substr($dir, $n*DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN) );
# spent 1.53ms making 544 calls to MARC::File::USMARC::CORE:unpack, avg 3µs/call
154
155 # Check directory validity
1565441.37ms ($tagno =~ /^[0-9A-Za-z]{3}$/)
# spent 1.37ms making 544 calls to MARC::File::USMARC::CORE:match, avg 3µs/call
157 or $marc->_warn( "Invalid tag in directory $location: \"$tagno\"" );
158
159544695µs ($len =~ /^\d{4}$/)
# spent 695µs making 544 calls to MARC::File::USMARC::CORE:match, avg 1µs/call
160 or $marc->_warn( "Invalid length in directory $location tag $tagno: \"$len\"" );
161
162544654µs ($offset =~ /^\d{5}$/)
# spent 654µs making 544 calls to MARC::File::USMARC::CORE:match, avg 1µs/call
163 or $marc->_warn( "Invalid offset in directory $location tag $tagno: \"$offset\"" );
164
165 ($offset + $len <= $reclen)
166 or $marc->_warn( "Directory entry $location runs off the end of the record tag $tagno" );
167
1685442.66ms my $tagdata = bytes::substr( $text, $data_start+$offset, $len );
# spent 2.66ms making 544 calls to bytes::substr, avg 5µs/call
169
170 # if utf8 the we encode the string as utf8
171108838.3ms if ( $marc->encoding() eq 'UTF-8' ) {
# spent 31.6ms making 544 calls to MARC::File::Encode::marc_to_utf8, avg 58µs/call # spent 6.70ms making 544 calls to MARC::Record::encoding, avg 12µs/call
172 $tagdata = marc_to_utf8( $tagdata );
173 }
174
1755441.41ms $marc->_warn( "Invalid length in directory for tag $tagno $location" )
# spent 1.41ms making 544 calls to bytes::length, avg 3µs/call
176 unless ( $len == bytes::length($tagdata) );
177
17810881.04ms if ( substr($tagdata, -1, 1) eq END_OF_FIELD ) {
179 # get rid of the end-of-tag character
180 chop $tagdata;
181 --$len;
182 } else {
183 $marc->_warn( "field does not end in end of field character in tag $tagno $location" );
184 }
185
186 warn "Specs: ", join( "|", $tagno, $len, $offset, $tagdata ), "\n" if $MARC::Record::DEBUG;
187
188 if ( $filter_func ) {
189 next unless $filter_func->( $tagno, $tagdata );
190 }
191
192512012.7ms6088.72ms if ( MARC::Field->is_controlfield_tag($tagno) ) {
# spent 6.43ms making 544 calls to MARC::Field::is_controlfield_tag, avg 12µs/call # spent 1.30ms making 32 calls to MARC::Field::new, avg 41µs/call # spent 990µs making 32 calls to MARC::Record::append_fields, avg 31µs/call
193 $marc->append_fields( MARC::Field->new( $tagno, $tagdata ) );
194 } else {
195 my @subfields = split( SUBFIELD_INDICATOR, $tagdata );
196 my $indicators = shift @subfields;
197 my ($ind1, $ind2);
198
1991024858µs if ( length( $indicators ) > 2 or length( $indicators ) == 0 ) {
200 $marc->_warn( "Invalid indicators \"$indicators\" forced to blanks $location for tag $tagno\n" );
201 ($ind1,$ind2) = (" ", " ");
202 } else {
203 $ind1 = substr( $indicators,0, 1 );
204 $ind2 = substr( $indicators,1, 1 );
205 }
206
207 # Split the subfield data into subfield name and data pairs
208 my @subfield_data;
209 for ( @subfields ) {
21013193.57ms if ( length > 0 ) {
211 push( @subfield_data, substr($_,0,1),substr($_,1) );
212 } else {
213 $marc->_warn( "Entirely empty subfield found in tag $tagno" );
214 }
215 }
216
217 if ( !@subfield_data ) {
218 $marc->_warn( "no subfield data found $location for tag $tagno" );
219 next;
220 }
221
22251226.7ms my $field = MARC::Field->new($tagno, $ind1, $ind2, @subfield_data );
# spent 26.7ms making 512 calls to MARC::Field::new, avg 52µs/call
2235121.98ms if ( $field->warnings() ) {
# spent 1.98ms making 512 calls to MARC::Field::warnings, avg 4µs/call
224 $marc->_warn( $field->warnings() );
225 }
2265128.61ms $marc->append_fields( $field );
# spent 8.61ms making 512 calls to MARC::Record::append_fields, avg 17µs/call
227 }
228 } # looping through all the fields
229
230
231 return $marc;
232}
233
234=head2 update_leader()
235
- -
243sub update_leader() {
244 my $self = shift;
245
246 my (undef,undef,$reclen,$baseaddress) = $self->_build_tag_directory();
247
248 $self->_set_leader_lengths( $reclen, $baseaddress );
249}
250
251=head2 _build_tag_directory()
252
- -
262sub _build_tag_directory {
263 my $marc = shift;
264 $marc = shift if (ref($marc)||$marc) =~ /^MARC::File/;
265 die "Wanted a MARC::Record but got a ", ref($marc) unless ref($marc) eq "MARC::Record";
266
267 my @fields;
268 my @directory;
269
270 my $dataend = 0;
271 for my $field ( $marc->fields() ) {
272 # Dump data into proper format
273 my $str = $field->as_usmarc;
274 push( @fields, $str );
275
276 # Create directory entry
277 my $len = bytes::length( $str );
278
279 my $direntry = sprintf( "%03s%04d%05d", $field->tag, $len, $dataend );
280 push( @directory, $direntry );
281 $dataend += $len;
282 }
283
284 my $baseaddress =
285 LEADER_LEN + # better be 24
286 ( @directory * DIRECTORY_ENTRY_LEN ) +
287 # all the directory entries
288 1; # end-of-field marker
289
290
291 my $total =
292 $baseaddress + # stuff before first field
293 $dataend + # Length of the fields
294 1; # End-of-record marker
295
- -
298 return (\@fields, \@directory, $total, $baseaddress);
299}
300
301=head2 encode()
302
- -
308sub encode() {
309 my $marc = shift;
310 $marc = shift if (ref($marc)||$marc) =~ /^MARC::File/;
311
312 my ($fields,$directory,$reclen,$baseaddress) = _build_tag_directory($marc);
313 $marc->set_leader_lengths( $reclen, $baseaddress );
314
315 # Glomp it all together
316 return join("",$marc->leader, @$directory, END_OF_FIELD, @$fields, END_OF_RECORD);
317}
31815µs1;
319
320__END__
 
# spent 3.15ms within MARC::File::USMARC::CORE:match which was called 1707 times, avg 2µs/call: # 544 times (1.37ms+0s) by MARC::File::USMARC::decode at line 156, avg 3µs/call # 544 times (695µs+0s) by MARC::File::USMARC::decode at line 159, avg 1µs/call # 544 times (654µs+0s) by MARC::File::USMARC::decode at line 162, avg 1µs/call # 25 times (255µs+0s) by MARC::File::USMARC::decode at line 122, avg 10µs/call # 25 times (100µs+0s) by MARC::File::USMARC::decode at line 109, avg 4µs/call # 25 times (80µs+0s) by MARC::File::USMARC::decode at line 114, avg 3µs/call
sub MARC::File::USMARC::CORE:match; # opcode
# spent 1.53ms within MARC::File::USMARC::CORE:unpack which was called 544 times, avg 3µs/call: # 544 times (1.53ms+0s) by MARC::File::USMARC::decode at line 153, avg 3µs/call
sub MARC::File::USMARC::CORE:unpack; # opcode