#!/usr/bin/env perl use warnings; use strict; use POSIX; sub usage { die qq{Usage: $0 [filename]\n}; } if ( scalar @ARGV > 1 ) { usage; } my $first_timestamp = undef; my $last_timestamp = undef; my $base_timestamp = undef; my @delays; my %signal_delay; my $points; LINE: while ( <> ) { chomp; if ( m{^# base timestamp: (\d+)} ) { if ( defined $base_timestamp ) { die "base timestamp multiply defined"; } else { $base_timestamp = $1; } next LINE; } elsif ( m{^#} ) { next LINE; } # parse and validate line my ( $timestamp, $event_type, $num_bytes, $delay ) = split /\s+/, $_; if ( not defined $num_bytes ) { die q{Format: timestamp event_type num_bytes [delay]}; } if ( $timestamp !~ m{^\d+$} ) { die qq{Invalid timestamp: $timestamp}; } if ( $num_bytes !~ m{^\d+$} ) { die qq{Invalid byte count: $num_bytes}; } if ( not defined $base_timestamp ) { die "logfile is missing base timestamp"; } $timestamp -= $base_timestamp; # correct for startup time variation if ( not defined $last_timestamp ) { $last_timestamp = $first_timestamp = $timestamp; } $last_timestamp = max( $timestamp, $last_timestamp ); # process the event if ( $event_type eq q{-} ) { if ( not defined $delay ) { die q{Departure format: timestamp - num_bytes delay}; } push @delays, $delay; $signal_delay{ $timestamp - $delay } = min( $delay, $signal_delay{ $timestamp - $delay } ); $points .= ($timestamp - $delay) / 1000.0 . " $delay\n"; } } sub max { my $maxval = - POSIX::DBL_MAX; for ( @_ ) { next unless defined $_; if ( $_ > $maxval ) { $maxval = $_; } } return $maxval; } sub min { my $minval = POSIX::DBL_MAX; for ( @_ ) { next unless defined $_; if ( $_ < $minval ) { $minval = $_; } } return $minval; } # calculate statistics if ( scalar @delays == 0 ) { die q{Must have at least one departure event}; } @delays = sort { $a <=> $b } @delays; my $pp95 = $delays[ 0.95 * scalar @delays ]; my $pp50 = $delays[ 0.5 * scalar @delays ]; # measure signal delay every millisecond # = minimum time for a message created at time t to get to receiver my @signal_delay_samples = sort { $a <=> $b } keys %signal_delay; for ( my $ts = $signal_delay_samples[ -1 ]; $ts >= $signal_delay_samples[ 0 ]; $ts-- ) { if ( not defined $signal_delay{ $ts } ) { $signal_delay{ $ts } = $signal_delay{ $ts + 1 } + 1; } } my $signal_delay_points; for ( my $ts = $signal_delay_samples[ 0 ]; $ts <= $signal_delay_samples[ -1 ]; $ts++ ) { $signal_delay_points .= $ts / 1000.0 . " " . $signal_delay{ $ts } . "\n"; } my @signal_delays = sort { $a <=> $b } values %signal_delay; my $pp95s = $signal_delays[ 0.95 * scalar @signal_delays ]; printf STDERR qq{95th percentile per-packet queueing delay: %.0f ms\n}, $pp95; printf STDERR qq{95th percentile signal delay: %.0f ms\n}, $pp95s; my $graph_max = $signal_delays[-1] * 1.2; # make graph open GNUPLOT, q{| gnuplot} or die; my $lower_limit = min( 30, int $pp50 ); print GNUPLOT <