sub mergeLogs { my ($day, @files) = @_; my @lines; foreach my $file (@files) { my $fh = openLogFile($file); if (! defined $fh) { warn "$0: ignoring file $file\n"; next; } warn "-> processing $file\n" if $opts{'verbose'} > 0; push @lines, grep { /Running|Dump|FromCB|Update/o && &filterLog } <$fh>; close $fh; } use Benchmark 'cmpthese'; cmpthese( -1, { 'ST' => sub { ( sortLinesST(\@lines) )[ 0 ] }, 'GRT' => sub { ( sortLinesGRT(\@lines) )[ 0 ] }, 'GRT2' => sub { ( sortLinesGRT2(\@lines))[ 0 ] }, 'GRT3' => sub { ( sortLinesGRT3(\@lines) )[ 0 ] }, } ); exit; } sub filterLog { return 0 if exists $opts{'day'} && ! /^$opts{'day'}/o; if (! exists $opts{'server'}) { if (/\* Running on (\w+) -/) { $opts{'server'} = lc $1; return 0; } } if (exists $opts{'start-time'} || exists $opts{'stop-time'}) { if (/(\d{2}:\d{2}:\d{2}\.\d{3})/o) { return 0 if exists $opts{'start-time'} && $1 lt $opts{'start-time'}; return 0 if exists $opts{'stop-time'} && $1 gt $opts{'stop-time'}; } } return 0 if exists $opts{'user'} && ! /[\(\[]\s*(?:$opts{'user'})/o; s/ {2,}/ /go; s/ ?: / /go; s/^((?:\S+ ){3}).+?\[?I\]?:/$1/o; s/ ACK (\w) / $1 ACK /o; warn $_ if $opts{'verbose'} > 3; return 1; } sub sortLinesST { my $href = shift; return [ map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { [ $_, /(\d{2}:\d{2}:\d{2}\.\d{3})/o ] } @$href ]; } sub sortLinesGRT { my $href = shift; return [ map { substr($_, 12) } sort map { /(\d{2}:\d{2}:\d{2}\.\d{3})/o; $1 . $_ } @$href ]; } sub sortLinesGRT2 { my $href = shift; return [ map { substr($_, 4) } sort map { /(\d{2}):(\d{2}):(\d{2})\.(\d{3})/o; pack ('NA*', ( $1*60 + $2 )*60 + "$3.$4" ) . $_ } @$href ]; } sub sortLinesGRT3 { my $href = shift; return [ @$href[ map { unpack "N", substr($_, -4) } sort map { $href->[$_] =~ /(\d{2}:\d{2}:\d{2}\.\d{3})/o; $1 . pack ("N", $_) } 0..$#$href ] ]; }