#!/usr/bin/perl

@pids = </proc/[0-9]*>;
die if (!scalar @pids);
map { s-^/proc/--; } @pids;

chdir("/proc") or die;

print "\033[2J";

my %last_vmstat = ();
my %vmstat = ();

for (;;select '','','',0.05) {
	print "\033[1H";

	open(IN,"< /proc/loadavg") or die;
	chomp($x = <IN>);
	print "Load: $x\033[K\n";
	close(IN);

	unless (scalar %last_vmstat) {
		%last_vmstat = %vmstat;
	}

	%vmstat = ();
	open(IN,"< /proc/vmstat") or die;
	while (<IN>) {
		chomp;
		my @kv = split(' ',$_,2);
		$vmstat{$kv[0]} = $kv[1];
	}
	close(IN);

	open(IN,"< /proc/diskstats") or die;
# 252       3 dm-3 33 0 264 124 0 0 0 0 0 124 124
	while (<IN>) {
		chomp;
		($stats) = /^\s*\S+\s+\S+\s+\S+\s+(.*)$/;
		@stat = split(' ',$stats);
		$vmstat{'nr_read_ios'}+= $stat[0];
		$vmstat{'nr_read_merges'}+= $stat[1];
		$vmstat{'nr_read_sectors'}+= $stat[2];
		$vmstat{'nr_read_ticks'}+= $stat[3];
		$vmstat{'nr_write_ios'}+= $stat[4];
		$vmstat{'nr_write_merges'}+= $stat[5];
		$vmstat{'nr_write_sectors'}+= $stat[6];
		$vmstat{'nr_write_ticks'}+= $stat[7];
		$vmstat{'nr_in_flight'}+= $stat[8];
		$vmstat{'nr_io_ticks'}+= $stat[9];
		$vmstat{'nr_time_in_queue'}+= $stat[10];
	}
	close(IN);
	
	my %vmstat_delta = ();
	if (scalar %last_vmstat) {
		foreach my $k (keys %vmstat) {
			my $d = $vmstat{$k} - $last_vmstat{$k};
			$vmstat_delta{$k} = $d;
		}
	}

	foreach my $k (qw[dirty writeback]) {
		$nr_k = "nr_$k";
		$v = sprintf("%-8u ",$vmstat{$nr_k});
		printf("%13s:%-8u ",$k,$v);
	}
	print "\033[K\n";
	foreach my $k (qw[read_ios read_merges read_sectors read_ticks]) {
		$nr_k = "nr_$k";
		printf("%13s:%-8u ",$k,$vmstat_delta{$nr_k});
	}
	print "\033[K\n";
	foreach my $k (qw[write_ios write_merges write_sectors write_ticks]) {
		$nr_k = "nr_$k";
		printf("%13s:%-8u ",$k,$vmstat_delta{$nr_k});
	}
	print "\033[K\n";
	foreach my $k (qw[pgpgin pgpgout]) {
		printf("%13s:%-8u ",$k,$vmstat_delta{$k});
	}
	print "\033[K\n";

#	nr_dirty 9002
#	nr_writeback 0
#	nr_unstable 0
#	nr_page_table_pages 311
#	nr_mapped 9216
#	nr_slab 89033
#	pgpgin 26314708058
#	pgpgout 22363625570

	foreach my $pid (@pids) {
		open(IN,"< $pid/wchan") or next;
		$wchan = <IN>;
		close(IN);
		open(IN,"< $pid/stat") or next;
		$stats = <IN>;
		close(IN);
		@stat = split(' ',$stats,4);
		next if ($stat[2] eq 'S');
		next if ($stat[0] == $$);
		pop(@stat);
		$stats = join("\t",@stat);
		printf("%-5s %-16s %-3s %s\033[K\n",$stat[0],$stat[1],$stat[2],$wchan);
	}
	print "\033[0J";	# Clear to end of page
	$| = 1;
	$| = 0;
}
