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_sumd_avg_sum_opt > EPSILON) optimal = 0; 
82  
83 
d_max_sum /= num_chunks; 
84 
d_max_sum_opt = PO_DELAY; 
85 
if (d_max_sumd_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 
} 