Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

converting 'ps' running times

by Random_Walk (Prior)
on Jun 01, 2015 at 15:42 UTC ( [id://1128589]=CUFP: print w/replies, xml ) Need Help??

Monitoring is my bread an butter. I had cause to re-write a script here that parses process running time from ps output.

ps -ef "%t %c" 29:23 swdmgr 3-09:32:03 RIM_Oracle_prog 07:13:13 ksh

That running time is days-hours:minutes:seconds. Where days and hours will only be there if non-zero. The existing code parsed it like this:

my ($days, $hours, $min, $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;

But I thought this was much more fun...

my $age; # age in seconds $age = $1 * 86400 if $time =~ s/(\d+)-//; # add days if there my ($hours,$min,$sec) = split /:/, $time; my @mult = (1, 60, 3600); for (reverse split /:/, $time) { # fun way to convert to seconds $age += $_ * shift @mult; # he he he :-) }

Cheers,
R.

Pereant, qui ante nos nostra dixerunt!

Replies are listed 'Best First'.
Re: converting 'ps' running times
by FreeBeerReekingMonk (Deacon) on Jun 01, 2015 at 16:56 UTC

    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 ...

      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; } },
Re: converting 'ps' running times
by bulrush (Scribe) on Sep 03, 2015 at 12:20 UTC
    These monitoring tools are for Ubuntu but you might find a pointer to something useful.

    Other utils, some built in to Ubuntu, are: top (ascii screen that updates top to show top processes, runs forever, hit q to exit), free -m, vmstat, iostat, iotop, sar, netstat. Try them, see what you like. :)

      I already use most of those in our monitoring. The scripts need to run on AIX v5 and v7, Solaris v10 and v11, HP-UX, RedHat and SUSE. So generaly we stick to a lowest common denominator of tools.

      Cheers,
      R.

      Pereant, qui ante nos nostra dixerunt!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://1128589]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2024-04-25 05:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found