Monitoring Disk IO per process

From Zarafa wiki

Revision as of 23:23, 23 November 2010 by Ynypokizek (Talk | contribs)
Jump to: navigation, search


UNDER COSTRUCTION, PLEASE SEE THIS POST IN RESERVE COPY


CLICK HERE


Monitoring disk IO per process

<BR> <font color=red>This article is a community contribution and may include unsupported configurations. </font> <BR><BR>

Newer Linux kernels have per-process I/O accounting and you can use the iotop tool to find out what’s performing I/O, but in some cases you'll want to find the source of an I/O problem in an older kernel. This article will describe a way to do I/O accounting per process on older kernels.


First get this script and name it: iodump <pre>

  1. !/usr/bin/env perl

=pod

=head1 NAME

iodump - Compute per-PID I/O stats for Linux when iotop/pidstat/iopp are not available.

=head1 SYNOPSIS

Prepare the system:

 dmesg -c
 /etc/init.d/klogd stop
 echo 1 > /proc/sys/vm/block_dump

Start the reporting:

 while true; do sleep 1; dmesg -c; done | perl iodump
 CTRL-C

Stop the system from dumping these messages:

 echo 0 > /proc/sys/vm/block_dump
 /etc/init.d/klogd start

=head1 LICENSE

This software is released to the public domain, with no guarantees whatsoever.

=cut

use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); use sigtrap qw(handler finish untrapped normal-signals);

my %tasks;

my $oktorun = 1; my $line; while ( $oktorun && (defined ($line = <>)) ) {

  my ( $task, $pid, $activity, $where, $device );
  ( $task, $pid, $activity, $where, $device )
     = $line =~ m/(\S+)\((\d+)\): (READ|WRITE) block (\d+) on (\S+)/;
  if ( !$task ) {
     ( $task, $pid, $activity, $where, $device )
        = $line =~ m/(\S+)\((\d+)\): (dirtied) inode \(.*?\) (\d+) on (\S+)/;
  }
  if ( $task ) {
     my $s = $tasks{$pid} ||= { pid => $pid, task => $task };
     ++$s->{lc $activity};
     ++$s->{activity};
     ++$s->{devices}->{$device};
  }

}

printf("%-15s %10s %10s %10s %10s %10s %s\n",

  qw(TASK PID TOTAL READ WRITE DIRTY DEVICES));

foreach my $task (

  reverse sort { $a->{activity} <=> $b->{activity} } values %tasks

) {

  printf("%-15s %10d %10d %10d %10d %10d %s\n",
     $task->{task}, $task->{pid},
     ($task->{'activity'}  || 0),
     ($task->{'read'}      || 0),
     ($task->{'write'}     || 0),
     ($task->{'dirty'}     || 0),
     join(', ', keys %{$task->{devices}}));

}

sub finish {

  my ( $signal ) = @_;
  if ( $oktorun ) {
     print STDERR "# Caught SIG$signal.\n";
     $oktorun = 0;
  }
  else {
     print STDERR "# Exiting on SIG$signal.\n";
     exit(1);
  }

} </pre>


Then turn on kernel messages about I/O: <pre> echo 1 > /proc/sys/vm/block_dump </pre>


This makes the kernel start writing messages about every I/O operation that takes place. Now all you have to do is get those messages and feed them into the iodump script: <pre> while true; do sleep 1; dmesg -c; done | perl iodump </pre>


Wait a little while, then cancel the script. The results should look something like the following: <pre>

  1. while true; do sleep 1; dmesg -c; done | perl iodump

^C# Caught SIGINT. TASK PID TOTAL READ WRITE DIRTY DEVICES firefox 4450 4538 251 4287 0 sda4, sda3 kjournald 2100 551 0 551 0 sda4 firefox 28452 185 185 0 0 sda4 kjournald 782 59 0 59 0 sda3 pdflush 31 30 0 30 0 sda4, sda3 syslogd 2485 2 0 2 0 sda3 firefox 28414 2 2 0 0 sda4, sda3 firefox 28413 1 1 0 0 sda4 firefox 28410 1 1 0 0 sda4 firefox 28307 1 1 0 0 sda4 firefox 28451 1 1 0 0 sda4 </pre>


When finished, turn off kernel messages about I/O: <pre> echo 0 > /proc/sys/vm/block_dump </pre>

Personal tools