Change how Diskstats waits for its first handful of samples.

This fixes two bugs -- One a rounding error, one a desyncronization
between the main program and the data gathering daemon.

Additionally, it changes how the daemon prints the very first
sample. Before it would unconditionally wait until the time was
%$sample-time, which meant that in a worst case scenario,
a user could be left waiting for a while before seeing a line
of output.
This commit changes that first wait to only sleep if less
than 20% away from %$sample-time.
This commit is contained in:
Brian Fraser
2012-02-01 12:14:09 -03:00
parent 3de8aa530b
commit 7c4c186978
4 changed files with 65 additions and 19 deletions

View File

@@ -2539,6 +2539,8 @@ use constant MKDEBUG => $ENV{MKDEBUG} || 0;
use base qw( Diskstats );
use POSIX qw( ceil );
sub new {
my ($class, %args) = @_;
my $self = $class->SUPER::new(%args);
@@ -2566,7 +2568,7 @@ sub group_by {
if ($self->interactive() && $self->{_iterations} >= 2) {
my $elapsed = ( $self->curr_ts() || 0 )
- ( $self->first_ts() || 0 );
if ( $ts > 0 && $elapsed >= $self->sample_time() ) {
if ( $ts > 0 && ceil($elapsed) >= $self->sample_time() ) {
$self->print_deltas(
header_callback => sub {
my ($self, @args) = @_;
@@ -2675,6 +2677,8 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0;
use base qw( Diskstats );
use POSIX qw( ceil );
sub new {
my ( $class, %args ) = @_;
my $self = $class->SUPER::new(%args);
@@ -2711,7 +2715,7 @@ sub _sample_callback {
my $elapsed = ($self->curr_ts() || 0)
- ($self->prev_ts() || 0);
if ( $ts > 0 && $elapsed >= $self->sample_time() ) {
if ( $ts > 0 && ceil($elapsed) >= $self->sample_time() ) {
$self->print_deltas(
max_device_length => 6,
@@ -2976,6 +2980,7 @@ sub run_interactive {
PTDEBUG && _d("Forked, child is", $child_pid);
$tmp_fh = $child_fh;
$tmp_fh->blocking(0);
Time::HiRes::sleep(0.5);
}
}
@@ -3029,7 +3034,7 @@ sub run_interactive {
while ($run) {
my $refresh_interval = $o->get('interval');
my $time = scalar Time::HiRes::gettimeofday();
my $sleep = $refresh_interval - fmod( $time, $refresh_interval );
my $sleep = ($refresh_interval - fmod( $time, $refresh_interval ))+0.5;
if ( my $input = read_command_timeout( $sel, $sleep ) ) {
if ($actions{$input}) {
@@ -3106,21 +3111,39 @@ sub gather_samples {
push @fhs, $fh;
}
STDOUT->autoflush(1);
push @fhs, \*STDOUT;
for my $fh ( @fhs ) {
$fh->autoflush(1);
}
Time::HiRes::sleep( $sample_interval
- fmod( scalar(Time::HiRes::gettimeofday()),
$sample_interval));
{
my $time = scalar(Time::HiRes::gettimeofday());
my $sleep = $sample_interval - fmod( $time,
$sample_interval);
PTDEBUG && _d("Child: Starting at [$time] "
. ($sleep < ($sample_interval * 0.2) ? '' : 'not ')
. "going to sleep [$sleep]");
Time::HiRes::sleep($sleep) if $sleep < ($sample_interval * 0.8);
open my $diskstats_fh, "<", "/proc/diskstats"
or die "Cannot open /proc/diskstats: $OS_ERROR";
my @to_print = timestamp();
push @to_print, <$diskstats_fh>;
for my $fh ( @fhs ) {
print { $fh } @to_print;
}
close $diskstats_fh or die $OS_ERROR;
}
GATHER_DATA:
while ( $args{gather_while}->() ) {
my $time_of_day = scalar(Time::HiRes::gettimeofday());
my $sleep = $sample_interval
- fmod( $time_of_day, $sample_interval );
- fmod( $time_of_day, $sample_interval );
Time::HiRes::sleep($sleep);
open my $diskstats_fh, "<", "/proc/diskstats"
@@ -3228,9 +3251,9 @@ sub help {
/) Enter a Perl regex to match disk names $device_re
z) Set the sample size in seconds $interval
i) Hide inactive disks $inact_disk
d) Set the refresh interval in seconds $disp_int
p) Pause the program
q) Quit the program
space) Print headers
------------------- Press any key to continue -----------------------
HELP