analy.in 3.94 KB
Newer Older
1
#!/usr/bin/perl
2
#
3
# Copyright (c) 2009, 2014 University of Utah and the Flux Group.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
23
#
24 25 26 27 28 29 30 31 32 33 34 35 36

use strict;
use warnings;
use POSIX qw(strftime ceil);

sub any (@) { $_ && return 1 for @_; 0 }

our ($START, @to_plot);
require "@prefix@/etc/node_usage.conf";

chdir "@prefix@/data/node_usage";

my $TOLERANCE = 0.05;
37
#my $TOLERANCE = 0.10;
38 39 40 41 42 43 44 45 46
my $TOLERANCE_INTERVAL = 1/3;

my $interval = 60*60;
my $interval_name = "hourly";

my $start = ceil($START / $interval) * $interval;

my @idxs = (0 .. $#to_plot);

47 48 49 50 51 52 53 54 55
my @start;
foreach (@idxs) {
    if (defined $to_plot[$_][2]) {
	$start[$_] = ceil($to_plot[$_][2] / $interval) * $interval;
    } else {
	$start[$_] = $start;
    }
}

56 57 58 59 60
my $prev_time = 0;
my @prev_data = map {0} @idxs;
my @total_so_far = map {0} @idxs;
my $next_cutoff = $start;

61
my @error_frac = map {0} @idxs;
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81

open F, "node_usage.raw";
open O, ">node_usage-$interval_name.dat";

our %d;

sub sum_usage_stats ($) {
    my ($n) = @_;
    my @res;
    foreach my $row (@to_plot) {
	my $r = 0;
	my $pcs = $row->[1];
	foreach (@$pcs) {
	    $r += $d{$_}[$n] if defined $d{$_}[$n];
	}
	push @res, $r;
    }
    return @res;
}

82
sub filter_w_start ($@) {
83 84
    my ($time,@list) = @_;
    return map {$time >= $start[$_] ? $list[$_] : 'NaN'} @idxs;
85 86
}

87 88 89 90 91
while (<F>) {
    chop;
    s/^(\d+) (\d+) // or die;
    my $time = $2;
    undef %d;
92 93 94 95 96 97 98 99 100
    while (s/^ ([\w\d\-\?]+): (\d+) (\d+) (\d+) (\d+) //) {
	my ($node,$total,$free,$invalid,$oos) = ($1,$2,$3,$4,$5);

	if (!defined($oos) || $free > $total - $oos) {
	    print STDERR "WARNING: $node: free ($free) > total ($total) - oos ($oos)\n";
	    $d{$node} = [$total, $free, $invalid];
	} else {
	    $d{$node} = [$total-$oos, $free, $invalid];
	}
101 102 103 104 105 106 107 108
    }
    no warnings 'uninitialized';
    my @num = sum_usage_stats(0);
    #die unless $time <= $start || $num[0] == 128 + 40;
    #die unless $time <= $start || $num[1] == 128;
    my @data = sum_usage_stats(1);
    my @error = sum_usage_stats(2);
    @data = map {$data[$_] + $error[$_]/2} @idxs;
109 110 111 112 113
    @data = map {$error[$_] > $num[$_]*$TOLERANCE 
		     ? 'NaN' : $data[$_]} @idxs;
#    if (any map {$error[$_] > $num[$_]*$TOLERANCE} @idxs) {
#	print STDERR "ERROR $time: ", join ('   ', map {"$error[$_] > ".$num[$_]*$TOLERANCE} @idxs), "\n";
#    }
114 115 116 117 118
    use warnings;
    
    my $combine = sub {
	my ($t) = (@_);
	my $frac = ($t - $prev_time)/$interval;
119 120 121 122
	foreach my $i (@idxs) {
	    if ($prev_data[$i] != $prev_data[$i]) { # ie NaN 
		$error_frac[$i] += $frac;
	    } else {
123 124 125 126 127 128 129 130
		$total_so_far[$i] += $prev_data[$i] * $frac;
	    }
	}
    };
    
    while ($time >= $next_cutoff) {
	&$combine($next_cutoff);
	my @free = @total_so_far;
131 132 133 134 135
	foreach my $i (@idxs) {
	    if ($error_frac[$i] > $TOLERANCE_INTERVAL) {
		$free[$i] = 'NaN';
	    } else {
		$free[$i] /= (1 - $error_frac[$i]);
136 137 138 139
	    }
	}
	my @alloc = map {$num[$_] - $free[$_]} @idxs;
	my $dtime = $next_cutoff - $interval;
140 141
	@free = filter_w_start $dtime, @free;
	@alloc = filter_w_start $dtime, @alloc;
142 143
	print O join(' ', $dtime, map {sprintf("%.1f", $_)} (@free, @alloc)),"\n" 
	    if $dtime >= $start;
144
	@error_frac = map {0} @idxs;
145 146 147 148 149 150 151 152 153 154
	@total_so_far = map {0} @idxs;
	$prev_time = $next_cutoff;
	$next_cutoff += $interval;
	
    }
    &$combine($time);
    
    $prev_time = $time;
    @prev_data = @data;
}
155 156
close(F);
exit(0);
157 158 159 160 161 162 163 164 165 166 167 168 169