#!/usr/bin/perl
use Expect;

$discard = 2;
$sample_interval = 20;

sub Usage {

    print "cpuavg [samples num_discards]\n\n";
    print " samples      = total samples at 1 sec intervals.\n";
    print " num_discards = number of smallest and highest value samples\n";
    print "                to discard in stats.\n\n";
    print "   e.g. cpuavg  OR  cpuavg 50 2\n";
    print "   (default values are 30 samples, with num_discards = 3)\n\n";

    exit;
}
    
$numArgs = $#ARGV + 1;

if ($numArgs !=0 && $numArgs!= 2)
{
    printf "Wrong number of args.\n\n";
    Usage;
}

if ($numArgs == 2)
{
    $sample_interval = $ARGV[0] + 1;
    $discard         = $ARGV[1];
}

#print "$sample_interval , $discard\n\n"; 

$command = Expect->spawn ("vmstat 1 $sample_interval");
$command->expect ($sample_interval + 10, "\$ "); 

$out = $command->before();
@lines = split (/[\n]/, $out);
    
print "\n";

for ($i = 3; $i <= $#lines ; ++$i)
{
    $line = $lines[$i];
    @sline = split (/\s+/, $line);
    
    
    $cpu_usr_u[$i-3] = @sline[14];
    $cpu_sys_u[$i-3] = @sline[15];

#    printf "usr: %3d   sys: %3d\n", $cpu_usr_u[$i-3], $cpu_sys_u[$i-3];
}

$tot_samples = $#lines-2;
$samples = $tot_samples - 2 * $discard;

printf "\nDiscarding first line.\n";
printf "\n%d total samples, discarding %d lowest and highest samples.\n", $tot_samples, $discard;
$sum = 0;

$cpu_usr_var_sum  = 0.0;
$cpu_usr_skew_sum = 0.0;
$cpu_usr_kurt_sum = 0.0;

@cpu_usr = sort {$a <=> $b} (@cpu_usr_u);
@cpu_sys = sort {$a <=> $b} (@cpu_sys_u);

for ($i = $discard; $i < $tot_samples-$discard; ++$i)
{
    $cpu_usr_sum = $cpu_usr_sum + $cpu_usr [$i]; 
    $cpu_sys_sum = $cpu_sys_sum + $cpu_sys [$i]; 
}

$cpu_usr_avg = $cpu_usr_sum / $samples;
$cpu_sys_avg = $cpu_sys_sum / $samples;

printf "\nSorted sample set:\n\n";

for ($i = $discard; $i < $tot_samples-$discard; ++$i)
{
    $usr_diff = ($cpu_usr[$i] - $cpu_usr_avg);
    $sys_diff = ($cpu_sys[$i] - $cpu_sys_avg);

    $cpu_usr_var_sum = $cpu_usr_var_sum + $usr_diff**2; 
    $cpu_sys_var_sum = $cpu_sys_var_sum + $sys_diff**2; 

    $cpu_usr_skew_sum = $cpu_usr_skew_sum + $usr_diff**3; 
    $cpu_sys_skew_sum = $cpu_sys_skew_sum + $sys_diff**3; 

    $cpu_usr_kurt_sum = $cpu_usr_kurt_sum + $usr_diff**4; 
    $cpu_sys_kurt_sum = $cpu_sys_kurt_sum + $sys_diff**4; 

    printf "usr: %3d   sys: %3d\n", $cpu_usr[$i], $cpu_sys[$i];

#    print "usr sample val $cpu_usr[$i]";

#    printf "   diff %5.2f, ^2 %5.2f, ^3 %5.2f, ^4 %5.2f, cumulative %5.2f, %5.2f, %5.2f\n", $usr_diff, $usr_diff**2, $usr_diff**3, $usr_diff**4, $cpu_usr_var_sum, $cpu_usr_skew_sum, $cpu_usr_kurt_sum;

#    print "sys sample val $cpu_sys[$i]";

#    printf "   diff %5.2f, ^2 %5.2f, ^3 %5.2f, ^4 %5.2f, cumulative %5.2f, %5.2f, %5.2f\n", $sys_diff, $sys_diff**2, $sys_diff**3, $sys_diff**4, $cpu_sys_var_sum, $cpu_sys_skew_sum, $cpu_sys_kurt_sum;
}

#printf "usr sums %5.2f, %5.2f, %5.2f\n",$cpu_usr_var_sum, $cpu_usr_skew_sum, $cpu_usr_kurt_sum;
#printf "sys sums %5.2f, %5.2f, %5.2f\n",$cpu_sys_var_sum, $cpu_sys_skew_sum, $cpu_sys_kurt_sum;

$cpu_usr_variance = $cpu_usr_var_sum / ($samples - 1);

if ($cpu_usr_var_sum != 0)
{
    $cpu_usr_skew     = (sqrt ($samples)) * $cpu_usr_skew_sum / (sqrt ($cpu_usr_var_sum**3));
    $cpu_usr_kurtosis = $cpu_usr_kurt_sum / ($samples * $cpu_usr_variance**2) - 3;
}
else
{
    $cpu_usr_skew     = 0;
    $cpu_usr_kurtosis = 0;
}

$cpu_sys_variance = $cpu_sys_var_sum / ($samples - 1);

if ($cpu_sys_variance !=0)
{
    $cpu_sys_skew     = (sqrt ($samples)) * $cpu_sys_skew_sum / (sqrt ($cpu_sys_var_sum**3));
    $cpu_sys_kurtosis = $cpu_sys_kurt_sum / ($samples * $cpu_sys_variance**2) - 3;
}
else
{
    $cpu_sys_skew     = 0;
    $cpu_sys_kurtosis = 0;
}

printf "\n";
printf "             USR        SYS\n\n";
printf "average:    %5.1f      %5.1f\n", $cpu_usr_avg,       $cpu_sys_avg;
printf "variance:   %5.1f      %5.1f\n", $cpu_usr_variance,  $cpu_sys_variance;
printf "skew:       %5.1f      %5.1f\n", $cpu_usr_skew,      $cpu_sys_skew;
printf "kurtosis:   %5.1f      %5.1f\n", $cpu_usr_kurtosis,  $cpu_sys_kurtosis;





