Statistics
| Branch: | Tag: | Revision:

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
}