sssimulator / stats.c @ master
History | View | Annotate | Download (7.09 KB)
1 | 86681e55 | luca | #include <stdio.h> |
---|---|---|---|
2 | #include <math.h> |
||
3 | #include "stats.h" |
||
4 | 32c9a7bc | Luca Baldesi | #include "sched.h" |
5 | #include "malloc.h" |
||
6 | 86681e55 | luca | |
7 | #define EPSILON 0.0000001 |
||
8 | #define DELAY_MAX 2*num_chunks+10 |
||
9 | f850347b | Luca Baldesi | #define ABS(a) (((a) >= 0) ? (a) : -(a)) |
10 | 32c9a7bc | Luca Baldesi | #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 | f850347b | Luca Baldesi | 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 | 32c9a7bc | Luca Baldesi | { |
96 | struct stats * stat;
|
||
97 | int convergence = 0; |
||
98 | double avg_delay = -1, avg_max_delay = -1, max_delay = -1, loss = -1; |
||
99 | f850347b | Luca Baldesi | int last_chunk, win_start, last_win_start;
|
100 | 32c9a7bc | Luca Baldesi | |
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 | f850347b | Luca Baldesi | 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 | 32c9a7bc | Luca Baldesi | { |
125 | 4d4d1b40 | Luca Baldesi | if (!window && !convergence_precision)
|
126 | window = num_chunks; |
||
127 | f850347b | Luca Baldesi | 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 | 32c9a7bc | Luca Baldesi | num_peers, &avg_delay, &avg_max_delay, |
132 | &max_delay, &loss); |
||
133 | f850347b | Luca Baldesi | if (stat->last_non_active > last_chunk)
|
134 | convergence = ((float)ABS(avg_delay - stat->avg_delay)) < convergence_precision ? 1 : 0; |
||
135 | 32c9a7bc | Luca Baldesi | 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 | 86681e55 | luca | |
146 | 52770a8f | Luca Baldesi | int status_print(FILE *f, struct peer *peers, int num_peers, struct chunk * chunks, int num_chunks, int t) |
147 | 86681e55 | luca | { |
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 | 52770a8f | Luca Baldesi | //if (!comp(i)) res = 0;
|
172 | if (chunks[i].received != num_peers) res = 0; |
||
173 | 86681e55 | luca | } |
174 | |||
175 | return res;
|
||
176 | } |
||
177 | |||
178 | 32c9a7bc | Luca Baldesi | int per_chunk_delay_analysis(FILE *stream, const struct chunk *chunks, int num_chunks, int num_peers) |
179 | 86681e55 | luca | { |
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 | 32c9a7bc | Luca Baldesi | 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 | 86681e55 | luca | |
188 | 32c9a7bc | Luca Baldesi | d_max_sum_opt = PO_DELAY; |
189 | 86681e55 | luca | d_avg_sum_opt = ilogb(num_peers) + (double)((num_peers-(1<<ilogb(num_peers)))*2+1)/num_peers; |
190 | |||
191 | 32c9a7bc | Luca Baldesi | 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 | 86681e55 | luca | if (stream) fprintf(stream, "Average chunk diffusion delay %f (optimal %f)\n", d_max_sum, d_max_sum_opt); |
196 | 32c9a7bc | Luca Baldesi | //if (!stream) printf("\tTESTresults\t%f\t%f\t%f\n", dropped, d_avg_sum, d_max_max);
|
197 | 86681e55 | luca | |
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 | } |