#!/usr/bin/perl -w

use strict;
use Statistics::Distributions;

my $last_thread = -1;
my $last_end;
my @ctx;
my %hist;

my $BUCKET_SIZE = $ARGV[1];
die if (!defined ($BUCKET_SIZE));

print "\n\nbucket size is $BUCKET_SIZE\n";

my $infn = $ARGV[0];
die if (!defined ($infn));

if (!(open INF, "cat  $infn |")) {
    if (!(open INF, "bzcat -cd $infn.bz2 |")) {
	die;
    }
}

while (my $line = <INF>) {
    if ($line =~ /^tracerec: ([0-9]+) ([0-9\.]+) ([0-9\.]+) /) {
	
	my $thread = $1;
	my $start = $2;
	my $end = $3;
	
	if ($last_thread != -1 && 
	    $thread != $last_thread) {
	    my $gap = 1000 * ($start - $last_end);
	    push @ctx, $gap;
	    my $bucket = int ($gap/$BUCKET_SIZE);
	    $hist{$bucket}++;
	}
	
	$last_thread = $thread;
	$last_end = $end;
    }
}

close INF;

my $len = scalar (@ctx);

sub bynum {
    $a <=> $b;
}

my @ctx2 = sort bynum @ctx;

open OUTF, ">".$infn."_hist.dat" or die;

foreach my $val (sort bynum keys %hist) {
    print OUTF $val*$BUCKET_SIZE." $hist{$val}\n";
}

close OUTF;

sub percentile ($$)
{
    my $pctile = (shift) / 100.0;
    my $x = shift;
    my @data = @$x;
    my $len = scalar (@data);
    return $data[int($len*$pctile)];
}

sub median ($) 
{
    return percentile (shift, 50);
}

sub mean ($)
{
    my $x = shift;
    my @data = @$x;
    my $total = 0.0;
    my $len = scalar (@data);

    foreach (@data) {
	$total += $_;
    }

    return $total / $len;
}

sub trim ($$)
{
    my $x = shift;
    my $frac = shift;
    my @data = @$x;
    my @data2 = @data;
    my $len = scalar (@data2);
    my $low = int($len*$frac);
    my $high = int($len-($len*$frac));
    my @data3 = @data2[$low..$high];
    return @data3;
}

sub stdev ($)
{
    my $x = shift;
    my @data = @$x;
    my $total;
    my $len = scalar (@data);

    my $avg = mean (\@data);

    $total = 0.0;
    foreach (@data) {
	my $inc = ($_ - $avg) * ($_ - $avg);
	#print "$_ $avg $inc\n";
	$total += $inc;
    }
    $total /= $len-1;

    return sqrt ($total);
}

sub confidence ($$)
{
    my $x = shift;
    my $conf = shift;
    my @data = @$x;
    my $avg = mean (\@data);
    my $a = 1.0-$conf;
    my $aa = 1.0-($a/2);
    my $z = -Statistics::Distributions::udistr ($aa);
    my $std = stdev (\@data);
    print "  stdev = $std\n";
    print "  z ($aa) = $z\n";
    my $low = $avg - ($z*$std/sqrt($len));
    my $high = $avg + ($z*$std/sqrt($len));
    return ($low, $high);
}

print "$infn :\n";
print "  25th %ile ".percentile(25,\@ctx2)."\n";
print "  50th %ile ".percentile(50,\@ctx2)."\n";
print "  75th %ile ".percentile(75,\@ctx2)."\n";
print "  mean = ".mean(\@ctx2)."\n";

my $cnt = scalar (@ctx2);
print "  $cnt total context switches\n";

print "\n";
print "after trimming:\n";
my @ctx3 = trim (\@ctx2, 0.10);
$cnt = scalar (@ctx3);
print "  $cnt total context switches\n";
print "  25th %ile ".percentile(25,\@ctx3)."\n";
print "  50th %ile ".percentile(50,\@ctx3)."\n";
print "  75th %ile ".percentile(75,\@ctx3)."\n";
print "  mean = ".mean(\@ctx3)."\n";

(my $low, my $high) = confidence (\@ctx3, 0.95);
print "  95% confidence that mean is in the range $low .. $high\n";



syntax highlighted by Code2HTML, v. 0.9.1