analy.in 2.8 KB
Newer Older
1
#!/usr/bin/perl
2
3
4
5
6
#
# EMULAB-COPYRIGHT
# Copyright (c) 2009 University of Utah and the Flux Group.
# All rights reserved.
#
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

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;
my $TOLERANCE_INTERVAL = 1/3;

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

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

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

29
30
31
32
33
34
35
36
37
my @start;
foreach (@idxs) {
    if (defined $to_plot[$_][2]) {
	$start[$_] = ceil($to_plot[$_][2] / $interval) * $interval;
    } else {
	$start[$_] = $start;
    }
}

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
my $prev_time = 0;
my @prev_data = map {0} @idxs;
my @total_so_far = map {0} @idxs;
my $next_cutoff = $start;

my $error_frac = 0;

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;
}

64
65
66
67
68
sub filter_w_start ($@) {
    my $time = shift @_;
    return map {$time >= $start[$_] ? $_[$_] : 'NaN'} @idxs;
}

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
while (<F>) {
    chop;
    s/^(\d+) (\d+) // or die;
    my $time = $2;
    undef %d;
    while (s/^ ([\w\d\-\?]+): (\d+) (\d+) (\d+) //) {
	$d{$1} = [$2, $3, $4];
    }
    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;
    if (any map {$error[$_] > $num[$_]*$TOLERANCE} @idxs) {
	#print STDERR "ERROR $time: $error\n";
	@data = map {'NaN'} @idxs;
    }
    use warnings;
    
    my $combine = sub {
	my ($t) = (@_);
	my $frac = ($t - $prev_time)/$interval;
	if ($prev_data[0] != $prev_data[0]) { # ie NaN
	    $error_frac += $frac;
	} else {
	    foreach my $i (@idxs) {
		$total_so_far[$i] += $prev_data[$i] * $frac;
	    }
	}
    };
    
    while ($time >= $next_cutoff) {
	&$combine($next_cutoff);
	my @free = @total_so_far;
	if ($error_frac > $TOLERANCE_INTERVAL) {
	    foreach my $i (@idxs) {
		$free[0] = 'NaN';
	    }
	} else {
	    foreach my $i (@idxs) {
		$free[$i] /= (1 - $error_frac);
	    }
	}
	my @alloc = map {$num[$_] - $free[$_]} @idxs;
	my $dtime = $next_cutoff - $interval;
116
117
	@free = filter_w_start $dtime, @free;
	@alloc = filter_w_start $dtime, @alloc;
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
	print O join(' ', $dtime, map {sprintf("%.1f", $_)} (@free, @alloc)),"\n" 
	    if $dtime >= $start;
	$error_frac = 0;
	@total_so_far = map {0} @idxs;
	$prev_time = $next_cutoff;
	$next_cutoff += $interval;
	
    }
    &$combine($time);
    
    $prev_time = $time;
    @prev_data = @data;
}