sssimulator / stats.c @ master
History | View | Annotate | Download (7.09 KB)
1 |
#include <stdio.h> |
---|---|
2 |
#include <math.h> |
3 |
#include "stats.h" |
4 |
#include "sched.h" |
5 |
#include "malloc.h" |
6 |
|
7 |
#define EPSILON 0.0000001 |
8 |
#define DELAY_MAX 2*num_chunks+10 |
9 |
#define ABS(a) (((a) >= 0) ? (a) : -(a)) |
10 |
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
11 |
|
12 |
extern float convergence_precision; |
13 |
extern int needs(int k, const struct peer *p); |
14 |
|
15 |
int chunk_is_active(int k,const struct peer *peers, int num_peers) |
16 |
{ |
17 |
int needed = 0; |
18 |
int i = 0; |
19 |
while (!needed && i < num_peers)
|
20 |
needed = needs(k, &(peers[i++])); |
21 |
|
22 |
return needed;
|
23 |
} |
24 |
|
25 |
void chunk_stats_print(const struct stats *s, int type) |
26 |
{ |
27 |
if (s)
|
28 |
{ |
29 |
switch(type) {
|
30 |
case PLAIN_STATS:
|
31 |
fprintf(stderr,"----------STATS---------------\n");
|
32 |
if (s->last_non_active >= 0) |
33 |
{ |
34 |
fprintf(stderr,"Elapsed time: %f\n", s->elapsed_time);
|
35 |
fprintf(stderr,"Last chunk out of the game: %d\n", s->last_non_active);
|
36 |
fprintf(stderr,"Average delay: %f\n", s->avg_delay);
|
37 |
fprintf(stderr,"Average maximum delay: %f\n", s->avg_max_delay);
|
38 |
fprintf(stderr,"Maximum delay: %f\n", s->max_delay);
|
39 |
fprintf(stderr,"Loss: %f\n", s->loss);
|
40 |
} |
41 |
else
|
42 |
fprintf(stderr,"All chunks are still active.\n");
|
43 |
fprintf(stderr,"------------------------------\n");
|
44 |
break;
|
45 |
case CSV_STATS:
|
46 |
//Time, last chunk, avg delay, avg max delay, max delay, loss
|
47 |
fprintf(stderr,"%f,%d,%f,%f,%f,%f\n", s->elapsed_time, s->last_non_active, s->avg_delay, s->avg_max_delay, s->max_delay, s->loss);
|
48 |
break;
|
49 |
default:
|
50 |
fprintf(stderr,"ERROR: Statistics format unknown.\n");
|
51 |
} |
52 |
|
53 |
} |
54 |
} |
55 |
|
56 |
//calculate per chunk delay statistics
|
57 |
//returns true if optimal
|
58 |
int per_chunk_stats_analysis(const struct chunk *chunks, int num_chunks, int num_peers, double *avg_delay, double *avg_max_delay, double *max_delay, double *loss) |
59 |
{ |
60 |
int c; //chunk, peer |
61 |
double d_avg_sum=0; //average of per chunk delays on each <chunk,node> |
62 |
double d_avg_sum_opt=0; //optimum of d_avg_sum |
63 |
double d_max_sum=0; //average of per chunk max delay on each chunk |
64 |
double d_max_sum_opt=0; //optimum of d_max_sum |
65 |
int optimal=1; // true if optimal |
66 |
double d_max_max = 0; |
67 |
double dropped = 0; |
68 |
|
69 |
for (c = 0; c < num_chunks; c++) { |
70 |
double d_avg=0; |
71 |
d_avg = chunks[c].avg_delay / chunks[c].received; |
72 |
d_max_sum += chunks[c].max_delay; |
73 |
d_avg_sum += d_avg; |
74 |
d_max_max = max(chunks[c].max_delay, d_max_max); |
75 |
dropped += (num_peers - chunks[c].received); |
76 |
} |
77 |
|
78 |
dropped /= (num_chunks * num_peers); |
79 |
d_avg_sum /= num_chunks; |
80 |
d_avg_sum_opt = ilogb(num_peers) + (double)((num_peers-(1<<ilogb(num_peers)))*2+1)/num_peers; |
81 |
if (d_avg_sum-d_avg_sum_opt > EPSILON) optimal = 0; |
82 |
|
83 |
d_max_sum /= num_chunks; |
84 |
d_max_sum_opt = PO_DELAY; |
85 |
if (d_max_sum-d_max_sum_opt > EPSILON) optimal = 0; |
86 |
|
87 |
*avg_delay = d_avg_sum; |
88 |
*avg_max_delay = d_max_sum; |
89 |
*loss = dropped; |
90 |
*max_delay = d_max_max; |
91 |
return optimal;
|
92 |
} |
93 |
|
94 |
int chunk_stats_converge(struct stats** s, const struct chunk *chunks, int num_chunks, const struct peer * peers, int num_peers, double elapsed_time, uint32_t window) |
95 |
{ |
96 |
struct stats * stat;
|
97 |
int convergence = 0; |
98 |
double avg_delay = -1, avg_max_delay = -1, max_delay = -1, loss = -1; |
99 |
int last_chunk, win_start, last_win_start;
|
100 |
|
101 |
if (*s == NULL) |
102 |
{ |
103 |
(*s) = (struct stats *) malloc (sizeof(struct stats)); |
104 |
(*s)->last_non_active = -1;
|
105 |
(*s)->avg_delay = -1;
|
106 |
(*s)->avg_max_delay = -1;
|
107 |
(*s)->max_delay = -1;
|
108 |
(*s)->loss = -1;
|
109 |
} |
110 |
stat = *s; |
111 |
|
112 |
stat->elapsed_time = elapsed_time; |
113 |
|
114 |
last_chunk = stat->last_non_active; |
115 |
while ((stat->last_non_active + 1) < num_chunks && |
116 |
!chunk_is_active(stat->last_non_active + 1, peers, num_peers))
|
117 |
stat->last_non_active++; |
118 |
|
119 |
win_start = window ? (((stat->last_non_active+1)/window)-1) * window : 0; |
120 |
last_win_start = window ? (((last_chunk+1)/window)-1) * window : 0; |
121 |
|
122 |
//fprintf(stderr,"[DEBUG] start: %d, last start: %d\n", win_start, last_win_start);
|
123 |
if (!window || (win_start >= 0 && win_start > last_win_start)) |
124 |
{ |
125 |
if (!window && !convergence_precision)
|
126 |
window = num_chunks; |
127 |
window = window ? window : stat->last_non_active + 1;
|
128 |
//fprintf(stderr,"[DEBUG] start: %d, length: %d\n", win_start, MIN(num_chunks - win_start, window));
|
129 |
per_chunk_stats_analysis(chunks + win_start, |
130 |
MIN(num_chunks - win_start, window), |
131 |
num_peers, &avg_delay, &avg_max_delay, |
132 |
&max_delay, &loss); |
133 |
if (stat->last_non_active > last_chunk)
|
134 |
convergence = ((float)ABS(avg_delay - stat->avg_delay)) < convergence_precision ? 1 : 0; |
135 |
stat->avg_delay = avg_delay; |
136 |
stat->max_delay = max_delay; |
137 |
stat->avg_max_delay = avg_max_delay; |
138 |
stat->loss = loss; |
139 |
} |
140 |
|
141 |
//fprintf(stderr,"convergence: %d(%f)\n", convergence, convergence_precision);
|
142 |
|
143 |
return convergence;
|
144 |
} |
145 |
|
146 |
int status_print(FILE *f, struct peer *peers, int num_peers, struct chunk * chunks, int num_chunks, int t) |
147 |
{ |
148 |
int i, j, res;
|
149 |
|
150 |
if (f) {
|
151 |
fprintf(f, "Time %d:\n", t);
|
152 |
for (i = 0; i < num_peers; i++) { |
153 |
fprintf(f,"\tPeer %d:", i);
|
154 |
for (j = 0; j < peers[i].buf_size; j++) { |
155 |
if (peers[i].chunks[j]) {
|
156 |
fprintf(f," %d", peers[i].chunks[j]->chunk);
|
157 |
#if 0
|
158 |
} else {
|
159 |
if (t > num_chunks + PO_DELAY)
|
160 |
printf(" time %d: peer %d misses chunk %d\n", t, i, j);
|
161 |
res = 0;
|
162 |
#endif
|
163 |
} |
164 |
} |
165 |
fprintf(f, "\n");
|
166 |
} |
167 |
} |
168 |
|
169 |
res = 1;
|
170 |
for (i = 0; i < num_chunks; i++) { |
171 |
//if (!comp(i)) res = 0;
|
172 |
if (chunks[i].received != num_peers) res = 0; |
173 |
} |
174 |
|
175 |
return res;
|
176 |
} |
177 |
|
178 |
int per_chunk_delay_analysis(FILE *stream, const struct chunk *chunks, int num_chunks, int num_peers) |
179 |
{ |
180 |
double d_avg_sum=0; //average of per chunk delays on each <chunk,node> |
181 |
double d_max_sum=0; //average of per chunk max delay on each chunk |
182 |
int optimal=1; // true if optimal |
183 |
double dropped = 0; |
184 |
double d_max_max = 0; |
185 |
double d_max_sum_opt=0; //optimum of d_max_sum |
186 |
double d_avg_sum_opt=0; //optimum of d_avg_sum |
187 |
|
188 |
d_max_sum_opt = PO_DELAY; |
189 |
d_avg_sum_opt = ilogb(num_peers) + (double)((num_peers-(1<<ilogb(num_peers)))*2+1)/num_peers; |
190 |
|
191 |
optimal = per_chunk_stats_analysis(chunks, num_chunks, num_peers, &d_avg_sum, &d_max_sum, &d_max_max, &dropped); |
192 |
|
193 |
if (stream) fprintf(stream, "Average chunk distribution delay %f (optimal %f)\n", d_avg_sum, d_avg_sum_opt); |
194 |
if (stream) fprintf(stream, "Maximum chunk distribution delay %f\n", d_max_max); |
195 |
if (stream) fprintf(stream, "Average chunk diffusion delay %f (optimal %f)\n", d_max_sum, d_max_sum_opt); |
196 |
//if (!stream) printf("\tTESTresults\t%f\t%f\t%f\n", dropped, d_avg_sum, d_max_max);
|
197 |
|
198 |
return optimal;
|
199 |
} |
200 |
|
201 |
//calculate per node delay statistics
|
202 |
void per_node_delay_analysis(FILE *stream, struct chunk *chunks, int num_chunks) |
203 |
{ |
204 |
#if 0
|
205 |
int p,c; //peer, chunk
|
206 |
|
207 |
int d_avg = 0; //average playout delay
|
208 |
for (p = 0; p < num_peers; p++) {
|
209 |
int d = 0;
|
210 |
for (c = 0; c < num_chunks; c++) {
|
211 |
if (peers[p].chunks[c]->completed - c > d) d = peers[p].chunks[c]->completed - c;
|
212 |
}
|
213 |
//fprintf(trace, "Node %d had max delay of %d \n", p, d);
|
214 |
d_avg += d;
|
215 |
}
|
216 |
//fprintf(trace, "Average playout delay %f\n", (double)d_avg/num_peers);
|
217 |
if (stream) fprintf(stream,"Average playout delay %f (optimal ?)\n", (double)d_avg/num_peers);
|
218 |
#endif
|
219 |
} |