Guest User

Untitled

a guest
Aug 17th, 2018
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.16 KB | None | 0 0
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. package TaskStatsV1;
  5. use base qw(Exporter);
  6. use File::Basename "dirname";
  7. use lib dirname(__FILE__);
  8. use Config;
  9.  
  10. #NASTY HACK:
  11.  
  12. our @EXPORT = qw(get_readable_stats get_stats register_pid unregister_pid);
  13. BEGIN {
  14. #some initialization code to test which module to load depending on the
  15. #kernel/arch that is found..
  16. #use the same arch-detect method as configure.pl
  17. sub _getarch() {
  18. #returns a module suffix for the supported architecture, or undef if
  19. #the architecture is not supported
  20. my $arch = "";
  21. if($Config{"archname"} =~ m/x86_64/) {
  22. #running on 64 bit kernel, 64 bit perl
  23. return "_amd64";
  24. }
  25. my $uname = `uname -a`;
  26. if ($uname =~ m/x86_64|amd64/) {
  27. printf(STDERR "%s:%d: WARNING! this module is one of the few things " .
  28. "that will not work properly on a 32-bit based userland with a 64 " .
  29. "bit kernel!\n", __FILE__, __LINE__);
  30. return undef
  31. }
  32. $arch .= "_i386";
  33. if ($uname =~ m/pae/i) {
  34. $arch .= "_PAE";
  35. }
  36. return $arch;
  37. }
  38. sub default_dummy(;$) {
  39. #dummy function, just return a hashref with the "err" key set to 1.
  40. #The get_stats routine below will do its job and consider that something
  41. #happened from the C program.. this isn't the best way to do this, but hopefully
  42. #it shouldn't cause things to crash.
  43. *get_readable_stats = sub { return { err => 1 }; };
  44. if($_[0]) {
  45. print STDERR $_[0];
  46. }
  47. }
  48. my $arch = _getarch();
  49. if(!$arch) {
  50. default_dummy();
  51. } else {
  52. my $module_name = "pacctinfo$arch";
  53. eval("require ${module_name};");
  54. if($@) {
  55. default_dummy(sprintf("%s:%d: couldn't load %s: %s\nUsing dummy get_readable_stats\n",
  56. __FILE__, __LINE__, $module_name, $@));
  57. } else {
  58. $module_name->import();
  59. eval("*get_readable_stats = \\&${module_name}::pacctinfo_get_readable_stats;");
  60. if($@) { print STDERR "$@\n"; }
  61. }
  62. }
  63. }
  64.  
  65.  
  66.  
  67.  
  68. use Time::HiRes qw(sleep usleep);
  69. use Scalar::Util qw(looks_like_number);
  70. use Data::Dumper;
  71. #this is an array of fields available in the struct taskstats provided in
  72. #<linux/taskstats.h>, see that header for an explanation of the fields.
  73. my @FIELDS = qw(cpu_count cpu_delay_total blkio_count blkio_delay_total
  74. swapin_count swapin_delay_total cpu_run_real_total cpu_run_virtual_total);
  75.  
  76. #keep a hash of {pid}{last_stats}
  77. my $procstats = {};
  78. my @monitored_pids;
  79.  
  80. sub register_pid {
  81. #performs simple initialization and registration of the PID
  82. #The registration functions are used to keep deltas;
  83. #Currently they don't do much, but are provided for symmetry
  84. #in case the module would need to be expanded/operated upon.
  85. #Currently these are essentially no-ops.
  86. my $pid = $_[0];
  87. print "Registering $pid\n";
  88. $procstats->{$pid} = undef;
  89. }
  90. sub unregister_pid {
  91. #Remove a PID from the registry.
  92. my $pid = $_[0];
  93. delete($procstats->{$pid});
  94. }
  95.  
  96. sub get_stats {
  97. #returns a list of (actual, deltas) statistics;
  98. #all statistics are integers; and are stored in a
  99. #hash using the FIELDS defined in /usr/include/linux/taskstats.h
  100. #If this function fails, a list of empty hashrefs are returned.
  101. my $pid = $_[0];
  102. my (%actual, %deltas);
  103. #$r is the actual (well.. wrapped, see C source) taskstats structure.
  104. #I'm avoiding dealing/passing/manipulating this directly as I'm really
  105. #edgy with swig setting/getting C objects, and funny things can happen (
  106. #ex. perl can apparently use numbers up to 250 digits, which would not scale
  107. #well with the struct which uses a 64 bit integer)
  108. my $r = get_readable_stats($pid);
  109. #the C module will set this field to nonzero if an error occurred
  110. #while retrieving process information
  111. if($r->{"err"}) {
  112. return ({},{});
  113. }
  114. #if we don't have a previous value, fill it in so we can calculate deltas
  115. if(!$procstats->{$pid}) {
  116. foreach (@FIELDS) {
  117. #first time stats are gathered, the 'old' and 'new' values should
  118. #be the same
  119. $actual{$_} = $procstats->{$pid}->{$_} = $r->{$_};
  120. $deltas{$_} = 0;
  121. }
  122. #phony delta, return..
  123. return (\%actual, \%deltas);
  124. }
  125. foreach (@FIELDS) {
  126. my $orig = $procstats->{$pid};
  127. $actual{$_} = $r->{$_};
  128. if($actual{$_} < $orig->{$_}) {
  129. #overlow detected, add $orig to $actual;
  130. $actual{$_} += $orig->{$_};
  131. }
  132. $deltas{$_} = abs($actual{$_} - $orig->{$_});
  133. $orig->{$_} = $actual{$_};
  134. }
  135. return (\%actual, \%deltas);
  136. }
  137.  
  138. #This is just some testcode
  139. if (!caller) {
  140. #perl has some real issues with buffer messups
  141. $| = 1;
  142. @monitored_pids = map(int, @ARGV);
  143. if(!@monitored_pids) {
  144. opendir(my $procps, "/proc");
  145. @monitored_pids = (map { int($_) } grep { looks_like_number($_) } (readdir($procps)));
  146. closedir($procps);
  147. }
  148. print STDERR "\nMonitoring ". @monitored_pids . " processes\n";
  149.  
  150. register_pid($_) foreach (@monitored_pids);
  151. while(1) {
  152. foreach (keys %$procstats) {
  153. my ($actual, $deltas) = get_stats($_);
  154. if((!%$actual)||(!%$deltas)) {
  155. print STDERR "something happened for $_: $!\n";
  156. unregister_pid($_);
  157. next;
  158. }
  159. foreach my $f (grep(!/count/, (@FIELDS))) {
  160. printf("%-25s %-15f DELTA: %-15f\n", $f,
  161. $actual->{$f}/ 1_000_000_000,
  162. $deltas->{$f} / 1_000_000_000);
  163. }
  164. }
  165. print "\n";
  166. sleep(0.5);
  167. }
  168. }
  169. 1;
Add Comment
Please, Sign In to add comment