/
rtbtrace.pl
executable file
·106 lines (81 loc) · 2.42 KB
/
rtbtrace.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#! /usr/bin/perl
# Real-time visualization of block accesses
# with a layout as old DOS defraggers
#
# Idea borrowed from seekwatcher [http://oss.oracle.com/~mason/seekwatcher/]
# Copyright (C) 2010 - Steve Schnepp - GPL
use strict;
use warnings;
use Curses;
use Time::HiRes qw(sleep);
# Should not buffer anything since we are "real-time"
$| = 1;
# Give the blocksize as first arg
my $nb_blocks_1k = shift;
if (! $nb_blocks_1k) {
die "Should give the number of 1k blocks as first arg";
}
my $win = Curses::new();
# Hide cursor
Curses::curs_set(0);
my $last_tstp = 0;
my $tstp_step = 1 / 25; # 25 Hz
# use non-blocking IO on stdin.
# Otherwise when there is no activity, the drawing is stalled
use IO::Handle;
STDIN->blocking(0);
my $io_ops = {};
while(1) {
my $line = <>;
if (! $line) { sleep $tstp_step; $io_ops = {}; draw($io_ops); $last_tstp += $tstp_step; next; }
chomp($line);
# 8,0 3 1 0.000000000 697 G W 223490 + 8 [kjournald]
my ($device, $cpu_id, $seqno, $tstp, $pid, $action, $mode, $offset, $dummy, $length, $detail) = split(/ +/, trim($line), 11);
# Only take complete lines
next unless $detail;
# Only take the C (completed) requests to take care of an eventual buffering/queuing
next unless $action eq 'C';
# Flush if needed. Assumes the data is timestamp ordered
if ($tstp > $last_tstp + $tstp_step) {
$last_tstp += $tstp_step;
# flush to img
draw($io_ops);
# flush the in-flight IO ops
$io_ops = {};
}
# Fill the in-flight IO ops
$io_ops->{$offset} = [ $mode, $length ];
} continue {
}
sub draw
{
my $io_ops = shift;
use Term::Size;
my ($columns, $rows) = Term::Size::chars *STDOUT{IO};
$rows --; # last row is status row
my $nb_chars = $columns * $rows;
my $blocks_per_char = int ($nb_blocks_1k * 2 / $nb_chars) + 1;
# Each frame we redraw everything
$win->clear();
# Update the status line
$win->addstr($rows, 0, sprintf("%.2f", $last_tstp));
# Iterate & fill the window
while (my ($offset, $value) = each %$io_ops) {
my $offset_in_chars = $offset / $blocks_per_char;
my $x = $offset_in_chars / $columns;
my $y = $offset_in_chars % $columns;
my $op = ($value->[0] =~ m/R/ ? "R" : "W");
my $len = int($value->[1] / $blocks_per_char) + 1;
$win->addstr($x, $y, $op x $len);
}
sleep($tstp_step);
$win->refresh();
}
# haaa.. this should really be part of Perl :-)
sub trim
{
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}