sub parse_data { my $procs = shift; my $cmds = shift; while () { if (/^(\d+)\s+(\d+)\s+\((.*?)\)\s+(.*)\s+$/) { my $time = $1; my $pid = $2; my $exe = $3; my $op = $4; if (/init/ && ! exists $procs->{$pid}) { $procs->{$pid} = { start => $time, end => 0, sys => 0, user => 0, }; } if ($op =~ /exit\swith\suser\s(\d+)\ssys\s(\d+)/) { my $user = $1; my $sys = $2; $procs->{$pid}->{end} = $time; $procs->{$pid}->{sys} = $sys; $procs->{$pid}->{user} = $user; # hwclock warps system time, so adjust, pretending it takes # no time to execute if ($exe =~ /hwclock/) { my $duration = $procs->{$pid}->{end} - $procs->{$pid}->{start}; my $tmp = $procs->{$pid}; $tmp->{start} += $duration; while ($tmp->{parent}) { $tmp = $procs->{$tmp->{parent}}; $tmp->{start} += $duration; if ($tmp->{end}) { $tmp->{end} += $duration; } } } } elsif ($op =~ /forks\s(\d+)/) { my $kid = $1; $procs->{$kid} = { start => $time, end => 0, parent => $pid, cmd => [$exe], sys => 0, user => 0, read => {}, write => {}, kids => {}, }; $procs->{$pid}->{kids}->{$kid} = 1; $cmds->{$exe} = {} unless $cmds->{$exe}; $cmds->{$exe}->{$kid} = 1; } elsif ($op =~ /execs\s(.*)/) { my $path = $1; my $bin = (splitpath($path))[2]; push @{$procs->{$pid}->{cmd}}, $bin; $cmds->{$bin} = {} unless $cmds->{$bin}; $cmds->{$bin}->{$pid} = 1; } elsif ($op =~ /reads\s(.*)/) { my $file = $1; $procs->{$pid}->{read}->{$file} = 0 unless $procs->{$pid}->{read}->{$file}; $procs->{$pid}->{read}->{$file}++; } elsif ($op =~ /writes\s(.*)/) { my $file = $1; $procs->{$pid}->{write}->{$file} = 0 unless $procs->{$pid}->{write}->{$file}; $procs->{$pid}->{write}->{$file}++; } } } } sub accumulate_stats { my $procs = shift; my $stats = shift; my $pid = shift; my $proc = $procs->{$pid}; my $nread = 0; my $nwrite = 0; foreach my $file (keys %{$proc->{read}}) { $nread += $proc->{read}->{$file}; } foreach my $file (keys %{$proc->{write}}) { $nwrite += $proc->{write}->{$file}; } my $cnread = $nread; my $cnwrite = $nwrite; my $csys = $proc->{sys}; my $cuser = $proc->{user}; foreach my $kid (keys %{$proc->{kids}}) { &accumulate_stats($procs, $stats, $kid); my $cstats = $stats->{$kid}; $cnread+= $cstats->[0]; $cnwrite+= $cstats->[1]; $csys+= $cstats->[2]; $cuser+= $cstats->[3]; } $stats->{$pid} = [ $nread, $nwrite, $proc->{sys}, $proc->{user}, $cnread, $cnwrite, $csys, $cuser ]; }