in reply to converting 'ps' running times

Interesting, however:
1) Comment out the split, you seem to not require that anymore
2) In a world where using the minimum amount of CPU cycles is a must to not hinder normal processes, consider this 16% faster alternative:

use Benchmark qw(:all); $count = -5; cmpthese( $count, { 'org' => sub { for my $etime (qw(3-12:12:12 11:22)) { my $age; my $time = $etime; $age = ($1 * 86400) if $time =~ s/(\d+)-//; #my ( $hours, $min, $sec ) = split /:/, $time; my @mult = ( 1, 60, 3600 ); for ( reverse split /:/, $time ) { $age += $_ * shift @mult; } } }, 'mod' => sub { for my $etime (qw(3-12:12:12 11:22)) { my $age; # age in seconds my $time = $etime; my @mult = ( 1, 60, 3600, 86400); for ( reverse split /[:\-]/, $time ) { $age += $_ * shift @mult; } } }, } );

edit (seems a post comment was not recorded): I like the line with "he he he"... adding it to my perl knowledge ...

Replies are listed 'Best First'.
Re^2: converting 'ps' running times
by Random_Walk (Prior) on Jun 02, 2015 at 08:41 UTC

    You are right about the extra split. it was a vestigial line from previous revisions; I've removed from my code now. I like the idea of chucking the - into the split too. But I ran the benchmark with some real data and it actually makes it slower! I tried a few more ways to skin this cat too.

    Here are the numbers:

    Rate index mod first new org index 1109/s -- -24% -38% -48% -52% # moved @mult out loop and +used index mod 1464/s 32% -- -18% -31% -36% # Your mod first 1780/s 61% 22% -- -16% -22% # The original long code new 2116/s 91% 45% 19% -- -8% # my version, but inline += + * shift for reverse split org 2288/s 106% 56% 29% 8% -- # my original update s/(\d+ +)-//; and split
    another run swaps things around a little:
    Rate index first mod org new index 1316/s -- -22% -28% -39% -43% first 1688/s 28% -- -8% -22% -26% mod 1829/s 39% 8% -- -15% -20% org 2154/s 64% 28% 18% -- -6% new 2292/s 74% 36% 25% 6% --

    this is perl v5.10.1 on redhat. Similar results with 5.8 on AIX.

    I Guess the s/(\d+)-//; is pretty fast as it does not search past the first numeric group in the time. Then the split /:/ is about the quickest way to break the remaining bit.

    Here is the code I used to benchmark, with the test data. Somewhat long...

    #!/usr/bin/perl use strict; use warnings; use Benchmark qw(:all); my $count = -10; # read ps data my @ps; while (<DATA>) { chomp; s/\s+//g; push @ps, $_; } cmpthese( $count, { 'first' => sub { no warnings; for my $time (@ps) { my ($days, $hours, $mins, $secs); if ($time=~/(\d+)-(\d{2}):(\d{2}):(\d{2})/){ $days=$1; $hours=$2; $mins=$3; $secs=$4; }elsif($time=~/(\d{2}):(\d{2}):(\d{2})/){ $hours=$1; $mins=$2; $secs=$3; }else{ ($mins,$secs)=split/:/,$time; } my $day_sec = $days*86400; my $hour_sec = $hours*3600; my $min_sec = $mins*60; my $secs_running = $day_sec+$hour_sec+$min_sec+$secs; } }, 'org' => sub { for my $time (@ps) { my $age; $age = ($1 * 86400) if $time =~ s/(\d+)-//; my @mult = (1, 60, 3600 ); for ( reverse split /:/, $time ) { $age += $_ * shift @mult; } } }, 'mod' => sub { for my $time (@ps) { my $age; # age in seconds my @mult = ( 1, 60, 3600, 86400); for ( reverse split /[:\-]/, $time ) { $age += $_ * shift @mult; } } }, 'new' => sub { for my $time (@ps) { my @mult = (1, 60, 3600); my $age; $age = $1 * 86400 if $time =~ s/(\d+)-//; # age in se +conds $age += $_ * shift @mult for reverse split /:/, $time; } }, 'index' => sub { my @mult = ( 1, 60, 3600, 86400); for my $time (@ps) { my $age; # age in seconds my $i = 0; for ( reverse split /-|:/, $time ) { $age += $_ * $mult[$i++]; } } }, } ); __DATA__ 101-05:45:56 48-22:14:41 101-05:45:18 61-18:27:18 101-05:45:50 101-05:45:49 101-05:45:03 101-05:45:49 101-05:45:13 101-05:45:20 101-05:45:19 101-05:44:56 101-05:45:17 101-05:45:13 101-05:45:13 101-05:45:13 101-05:45:14 101-05:45:04 101-05:45:13 101-05:45:23 101-05:45:13 101-05:45:13 101-05:45:19 101-05:45:13 101-05:45:17 101-05:45:29 101-05:45:29 101-05:45:29 101-05:45:11 101-05:45:15 101-05:45:29 101-05:45:29 101-05:45:29 101-05:44:55 101-05:45:29 101-05:45:40 101-05:45:29 101-05:45:08 101-05:45:07 101-05:39:12 101-05:45:03 6-19:18:01 6-19:18:00 33-19:40:33 101-05:45:02 101-05:45:01 61-18:27:18 101-05:44:59 00:00 48-22:14:42 6-19:18:01 101-05:38:36 4-01:29:56 48-22:12:07 101-05:39:14 101-05:45:01 84-15:02:32 101-05:45:07 101-05:19:22 04:19 101-05:45:14 101-05:45:15 101-05:45:15 101-05:45:17 101-05:45:15 00:01 101-05:45:03 101-05:38:54 101-05:45:11 101-05:45:07 101-05:45:02 101-05:45:03 101-05:45:03 101-05:45:01 101-05:45:03 101-05:45:02 101-05:45:01 101-05:45:03 101-05:45:03 48-22:14:43 03:29:17 6-19:18:01 101-05:41:19 101-05:38:37 101-05:38:35 03:29:17 48-22:15:13 48-22:16:30 101-05:38:58 101-05:19:24 4-01:28:52 6-21:11:06 101-05:39:12 101-05:39:04 101-05:39:12 101-05:39:07 22:33:25 6-19:18:01 6-19:17:52 6-19:17:53 101-05:38:18 6-19:08:23 03:29:17 48-22:14:43 101-05:39:11 32-19:11:36 84-15:02:32 6-19:17:33 04:19 09:34 48-22:14:41 4-01:29:12 08:32:59 00:34 4-01:30:04 03:29:17 4-01:30:11 4-01:28:33 03:29:17 48-22:14:41 6-19:18:01 1-05:38:18 48-22:14:43 48-22:15:39 6-19:18:01 6-19:17:33 48-22:14:45 03:29:17 32-19:11:37 03:29:17 03:19 4-01:28:44 32-19:11:37 4-01:28:36 08:57:03 1-22:02:55 6-19:17:53 01:58 00:00 6-19:13:19

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!

      I stand corrected! I did not do a benchmark test with exhaustive input...
      and you came up with an even faster method to boot... chapeau!

      edit, new version, 2% faster:

      'newB' => sub { for my $time (@ps) { my @mult = (1, 60, 3600); my $age = $time =~ s/^(\d+)-// ? $1 * 86400 : 0; # ag +e in seconds $age += $_ * shift @mult for reverse split /:/, $time; } },