[padb-devel] [padb commit] r43 - Work on proc-info and proc-format, measure percent

codesite-noreply at google.com codesite-noreply at google.com
Thu Jun 11 10:58:14 BST 2009


Author: apittman
Date: Thu Jun 11 02:57:52 2009
New Revision: 43

Modified:
    trunk/src/padb

Log:
Work on proc-info and proc-format, measure percent
cpu usage ourself based on jiffies rather than using
the figure presented by ps.  Overhaul the proc-format
option so it aligns columns nicely with a properly
readable format.


Modified: trunk/src/padb
==============================================================================
--- trunk/src/padb	(original)
+++ trunk/src/padb	Thu Jun 11 02:57:52 2009
@@ -2727,6 +2727,79 @@
      print("$s\n");
  }

+sub show_proc_format {
+    my ( $nlines, $mode, $handle ) = @_;
+
+    my $lines = $nlines->{lines};
+
+    my @proc_format_array;
+    my $show_fields = 0;
+
+    my %proc_format_lengths;
+
+    # Split the command line options into a array.
+    foreach my $format (@proc_format) {
+        my @i = split( ",", $format );
+        foreach my $j (@i) {
+            my $key = lc($j);
+            push @proc_format_array, $key;
+            $proc_format_lengths{$key} = length($key);
+            $show_fields = 1 if ( $key eq "fields" );
+        }
+    }
+
+    my @all;
+    foreach my $tag ( sort ( keys %$lines ) ) {
+        my %hash;
+        $hash{vp} = $tag;
+        foreach my $data ( @{ $lines->{$tag} } ) {
+            if ( $data =~ /([\w\.]+)\:[ \t]*(.+)/ ) {
+                my $key = lc($1);
+
+                next unless defined $proc_format_lengths{$key};
+
+                if ( length($2) > $proc_format_lengths{$key} ) {
+                    $proc_format_lengths{$key} = length($2);
+                }
+
+                $hash{$key} = $2;
+            }
+        }
+        if ($show_fields) {
+            my @fields = sort ( keys(%hash) );
+            print "@fields\n";
+            exit(0);
+        }
+        push @all, \%hash;
+    }
+    @all = sort_proc_hashes( $conf{"proc-sort-key"}, @all );
+
+    if ( $conf{"proc-show-header"} ) {
+        my @res;
+        foreach my $key (@proc_format_array) {
+            my $l .= sprintf( "%$proc_format_lengths{$key}s", $key );
+            push @res, $l;
+        }
+        print "@res\n";
+
+        #print "@proc_format_array\n";
+    }
+    foreach my $hash (@all) {
+        my @res;
+        my @res;
+        foreach my $key (@proc_format_array) {
+            my $value = "?";
+            if ( defined $hash->{$key} ) {
+                $value = $hash->{$key};
+
+            }
+            push @res, sprintf( "%$proc_format_lengths{$key}s", $value );
+        }
+        print "@res\n";
+    }
+
+}
+
  sub show_results {
      my ( $nlines, $mode, $handle ) = @_;

@@ -2776,48 +2849,7 @@
              }
          }
      } elsif ( $mode eq "pinfo" and $#proc_format != -1 ) {
-        my @proc_format_array;
-        my $show_fields = 0;
-
-        foreach my $format (@proc_format) {
-            my @i = split( ",", $format );
-            foreach my $j (@i) {
-                my $key = lc($j);
-                push @proc_format_array, $key;
-                $show_fields = 1 if ( $key eq "fields" );
-            }
-        }
-
-        my @all;
-        foreach my $tag ( sort ( keys %$lines ) ) {
-            my %hash;
-            $hash{vp} = $tag;
-            foreach my $data ( @{ $lines->{$tag} } ) {
-                if ( $data =~ /(\w+)\:[ \t]*(.+)/ ) {
-                    $hash{ lc($1) } = $2;
-                }
-            }
-            if ($show_fields) {
-                my @fields = sort ( keys(%hash) );
-                print "@fields\n";
-                exit(0);
-            }
-            push @all, \%hash;
-        }
-        @all = sort_proc_hashes( $conf{"proc-sort-key"}, @all );
-
-        if ( $conf{"proc-show-header"} ) {
-            print "@proc_format_array\n";
-        }
-        foreach my $hash (@all) {
-            my @res;
-            foreach my $key (@proc_format_array) {
-                if ( defined $hash->{$key} ) {
-                    push @res, $hash->{$key};
-                }
-            }
-            print "@res\n";
-        }
+        show_proc_format( $nlines, $mode, $handle );
      }
  }

@@ -4742,17 +4774,16 @@
              output $vp, "exe:$exe";
          }

-        # It should be possible to calculate this from info
-        # in /proc but I've not discovered a way so do it
-        # so for now just call ps.
-        # Turns out this isn't great either, ps reports time
+        # pcpu is calculated from /proc elsewhere.
+        # This isn't either, ps reports time
          # as a percentage since the program started so
          # isn't live as the top-reported figure is.
-        my $pcpu = `ps --pid $pid -o pcpu= 2>/dev/null`;
-        chomp($pcpu);
-        if ( $pcpu != "" ) {
-            output( $vp, "pcpu:$pcpu%" );
-        }
+
+        #my $pcpu = `ps --pid $pid -o pcpu= 2>/dev/null`;
+        #chomp($pcpu);
+        #if ( $pcpu != "" ) {
+        #    output( $vp, "pcpu:$pcpu%" );
+        #}

          show_task_file( $vp, "$dir/status" );
          show_task_file( $vp, "$dir/wchan", "wchan" );
@@ -4833,6 +4864,120 @@
      }
  }

+# Convert the first line of /proc/stat to elapsed jiffies.
+sub string_to_jiffies {
+    my ($ps) = @_;
+
+    my @usecc = split( " ", $ps );
+
+    my $jiffies = 0;
+
+    # Remove the "cpu" prefix.
+    shift(@usecc);
+    foreach my $usecv (@usecc) {
+        $jiffies += $usecv;
+    }
+    return $jiffies;
+}
+
+sub add_and_divide_jiffies {
+    my ( $pre, $post ) = @_;
+
+    my $jiffies;
+
+    my @pre = split( " ", $pre );
+
+    return ( ( string_to_jiffies($pre) + string_to_jiffies($post) ) / 2 );
+}
+
+# Convert /proc/self/stat into used jiffies.
+sub stat_to_jiffies {
+    my $stat    = shift;
+    my @values  = split( " ", $stat );
+    my $jiffies = 0;
+    $jiffies += $values[13];    # utime
+    $jiffies += $values[14];    # stime
+    return $jiffies;
+}
+
+sub show_proc_all {
+    my ($list) = @_;
+
+    my @all;
+
+    foreach my $proc ( @{$list} ) {
+        my $pid = $proc->{pid};
+        open( $proc->{handle}, "/proc/$pid/stat" );
+    }
+
+    open( SFD, "/proc/stat\n" );
+
+    # Begin critical path.
+    my $stat = <SFD>;
+
+    foreach my $proc ( @{$list} ) {
+        my $pid = $proc->{pid};
+        my $h   = $proc->{handle};
+        $proc->{stat_start} = <$h>;
+        seek( $proc->{handle}, 0, 0 );
+    }
+
+    seek( SFD, 0, 0 );
+    my $stat2 = <SFD>;
+
+    # End critical path.
+
+    my $jiffies_start = add_and_divide_jiffies( $stat, $stat2 );
+
+    foreach my $proc ( @{$list} ) {
+        my $vp  = $proc->{vp};
+        my $pid = $proc->{pid};
+        show_proc( $vp, $pid );
+    }
+
+    sleep(1);
+
+    seek( SFD, 0, 0 );
+
+    # Begin critical path.
+    $stat = <SFD>;
+
+    foreach my $proc ( @{$list} ) {
+        my $pid = $proc->{pid};
+        my $h   = $proc->{handle};
+        $proc->{stat_end} = <$h>;
+        close( $proc->{handle} );
+    }
+
+    seek( SFD, 0, 0 );
+    $stat2 = <SFD>;
+
+    # End critical path.
+
+    my $cpucount = 0;
+    while (<SFD>) {
+        if ( $_ =~ /^cpu\d/ ) {
+            $cpucount++;
+        }
+    }
+    close(SFD);
+
+    my $jiffies_end = add_and_divide_jiffies( $stat, $stat2 );
+
+    my $elapsed = $jiffies_end - $jiffies_start;
+
+    foreach my $proc ( @{$list} ) {
+        my $vp       = $proc->{vp};
+        my $jpre     = stat_to_jiffies( $proc->{stat_start} );
+        my $jpost    = stat_to_jiffies( $proc->{stat_end} );
+        my $jused    = $jpost - $jpre;
+        my $used     = ( $jused / $elapsed ) * $cpucount * 100;
+        my $used_str = sprintf( "%d", $used );
+
+        output( $vp, "pcpu: $used_str" );
+    }
+}
+
  sub show_proc {
      my ( $vp, $pid ) = @_;

@@ -5832,10 +5977,10 @@
      };

      $allfns{pinfo} = {
-        'handler'   => \&show_proc,
-        'arg_long'  => 'proc-info',
-        'help'      => "Show process information",
-        'options_i' => {
+        'handler_all' => \&show_proc_all,
+        'arg_long'    => 'proc-info',
+        'help'        => "Show process information",
+        'options_i'   => {
              "proc-shows-proc" => 1,
              "proc-shows-fds"  => 1,
              "proc-shows-maps" => 0,




More information about the padb-devel mailing list