Store sourcestats samples in circular buffer
The samples now don't have to be moved when pruning the register.
This commit is contained in:
parent
d841c86a6e
commit
a3d47ffc81
1 changed files with 58 additions and 69 deletions
127
sourcestats.c
127
sourcestats.c
|
@ -62,11 +62,13 @@ struct SST_Stats_Record {
|
|||
unsigned long refid;
|
||||
IPAddr *ip_addr;
|
||||
|
||||
/* Number of samples currently stored. sample[n_samples-1] is the
|
||||
newest. The samples are expected to be sorted in order, but that
|
||||
probably doesn't matter. */
|
||||
/* Number of samples currently stored. The samples are stored in circular
|
||||
buffer. */
|
||||
int n_samples;
|
||||
|
||||
/* The index of the newest sample */
|
||||
int last_sample;
|
||||
|
||||
/* The index in the registers of the best individual sample that we
|
||||
are holding, in terms of the minimum root distance at the present
|
||||
time */
|
||||
|
@ -165,6 +167,7 @@ SST_CreateInstance(unsigned long refid, IPAddr *addr)
|
|||
inst->refid = refid;
|
||||
inst->ip_addr = addr;
|
||||
inst->n_samples = 0;
|
||||
inst->last_sample = 0;
|
||||
inst->estimated_frequency = 0;
|
||||
inst->skew = 2000.0e-6;
|
||||
inst->skew_dirn = SST_Skew_Nochange;
|
||||
|
@ -187,21 +190,6 @@ SST_DeleteInstance(SST_Stats inst)
|
|||
return;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
move_stats_entry(SST_Stats inst, int src, int dest)
|
||||
{
|
||||
inst->sample_times[dest] = inst->sample_times[src];
|
||||
inst->offsets[dest] = inst->offsets[src];
|
||||
inst->orig_offsets[dest] = inst->orig_offsets[src];
|
||||
inst->peer_delays[dest] = inst->peer_delays[src];
|
||||
inst->peer_dispersions[dest] = inst->peer_dispersions[src];
|
||||
inst->root_delays[dest] = inst->root_delays[src];
|
||||
inst->root_dispersions[dest] = inst->root_dispersions[src];
|
||||
inst->strata[dest] = inst->strata[src];
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* This function is called to prune the register down when it is full.
|
||||
For now, just discard the oldest sample. */
|
||||
|
@ -209,20 +197,8 @@ move_stats_entry(SST_Stats inst, int src, int dest)
|
|||
static void
|
||||
prune_register(SST_Stats inst, int new_oldest)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!(new_oldest < inst->n_samples)) {
|
||||
CROAK("new_oldest should be < n_samples");
|
||||
}
|
||||
|
||||
for (i=0, j=new_oldest; j<inst->n_samples; j++) {
|
||||
if (j != i) {
|
||||
move_stats_entry(inst, j, i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
inst->n_samples = i;
|
||||
|
||||
assert(inst->n_samples >= new_oldest);
|
||||
inst->n_samples -= new_oldest;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -240,7 +216,7 @@ SST_AccumulateSample(SST_Stats inst, struct timeval *sample_time,
|
|||
prune_register(inst, 1);
|
||||
}
|
||||
|
||||
n = inst->n_samples;
|
||||
n = inst->last_sample = (inst->last_sample + 1) % MAX_SAMPLES;
|
||||
|
||||
inst->sample_times[n] = *sample_time;
|
||||
inst->offsets[n] = offset;
|
||||
|
@ -252,7 +228,15 @@ SST_AccumulateSample(SST_Stats inst, struct timeval *sample_time,
|
|||
inst->strata[n] = stratum;
|
||||
|
||||
++inst->n_samples;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
/* Return index of the i-th sample in the circular buffer */
|
||||
|
||||
static int
|
||||
get_buf_index(SST_Stats inst, int i)
|
||||
{
|
||||
return (unsigned int)(inst->last_sample + MAX_SAMPLES - inst->n_samples + i + 1) % MAX_SAMPLES;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -266,10 +250,11 @@ convert_to_intervals(SST_Stats inst, double *times_back)
|
|||
struct timeval *newest_tv;
|
||||
int i;
|
||||
|
||||
newest_tv = &(inst->sample_times[inst->n_samples - 1]);
|
||||
newest_tv = &(inst->sample_times[inst->last_sample]);
|
||||
for (i=0; i<inst->n_samples; i++) {
|
||||
/* The entries in times_back[] should end up negative */
|
||||
UTI_DiffTimevalsToDouble(&(times_back[i]), &(inst->sample_times[i]), newest_tv);
|
||||
UTI_DiffTimevalsToDouble(×_back[i],
|
||||
&inst->sample_times[get_buf_index(inst, i)], newest_tv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,20 +268,21 @@ find_best_sample_index(SST_Stats inst, double *times_back)
|
|||
|
||||
double root_distance, best_root_distance;
|
||||
double elapsed;
|
||||
int i, n, best_index;
|
||||
int i, j, l, n, best_index;
|
||||
|
||||
n = inst->n_samples - 1;
|
||||
best_root_distance = inst->root_dispersions[n] + 0.5 * fabs(inst->root_delays[n]);
|
||||
best_index = n;
|
||||
best_index = l = inst->last_sample;
|
||||
best_root_distance = inst->root_dispersions[l] + 0.5 * fabs(inst->root_delays[l]);
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_SourceStats, "n=%d brd=%f", n, best_root_distance);
|
||||
#endif
|
||||
for (i=0; i<n; i++) {
|
||||
j = get_buf_index(inst, i);
|
||||
elapsed = -times_back[i];
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_SourceStats, "n=%d i=%d latest=[%s] doing=[%s] elapsed=%f", n, i,
|
||||
UTI_TimevalToString(&(inst->sample_times[n])),
|
||||
UTI_TimevalToString(&(inst->sample_times[i])),
|
||||
UTI_TimevalToString(&inst->sample_times[l]),
|
||||
UTI_TimevalToString(&inst->sample_times[j]),
|
||||
elapsed);
|
||||
#endif
|
||||
|
||||
|
@ -304,17 +290,17 @@ find_best_sample_index(SST_Stats inst, double *times_back)
|
|||
if (elapsed <= 0.0) {
|
||||
LOG(LOGS_ERR, LOGF_SourceStats, "Elapsed<0! n=%d i=%d latest=[%s] doing=[%s] elapsed=%f",
|
||||
n, i,
|
||||
UTI_TimevalToString(&(inst->sample_times[n])),
|
||||
UTI_TimevalToString(&(inst->sample_times[i])),
|
||||
UTI_TimevalToString(&inst->sample_times[l]),
|
||||
UTI_TimevalToString(&inst->sample_times[j]),
|
||||
elapsed);
|
||||
|
||||
elapsed = fabs(elapsed);
|
||||
}
|
||||
|
||||
root_distance = inst->root_dispersions[i] + elapsed * inst->skew + 0.5 * fabs(inst->root_delays[i]);
|
||||
root_distance = inst->root_dispersions[j] + elapsed * inst->skew + 0.5 * fabs(inst->root_delays[j]);
|
||||
if (root_distance < best_root_distance) {
|
||||
best_root_distance = root_distance;
|
||||
best_index = i;
|
||||
best_index = j;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,13 +332,14 @@ void
|
|||
SST_DoNewRegression(SST_Stats inst)
|
||||
{
|
||||
double times_back[MAX_SAMPLES];
|
||||
double offsets[MAX_SAMPLES];
|
||||
double peer_distances[MAX_SAMPLES];
|
||||
double weights[MAX_SAMPLES];
|
||||
|
||||
int degrees_of_freedom;
|
||||
int best_start;
|
||||
double est_intercept, est_slope, est_var, est_intercept_sd, est_slope_sd;
|
||||
int i, nruns;
|
||||
int i, j, nruns;
|
||||
double min_distance;
|
||||
double sd_weight;
|
||||
double old_skew, old_freq, stress;
|
||||
|
@ -363,7 +350,9 @@ SST_DoNewRegression(SST_Stats inst)
|
|||
|
||||
if (inst->n_samples > 0) {
|
||||
for (i=0; i<inst->n_samples; i++) {
|
||||
peer_distances[i] = 0.5 * fabs(inst->peer_delays[i]) + inst->peer_dispersions[i];
|
||||
j = get_buf_index(inst, i);
|
||||
offsets[i] = inst->offsets[j];
|
||||
peer_distances[i] = 0.5 * fabs(inst->peer_delays[j]) + inst->peer_dispersions[j];
|
||||
}
|
||||
|
||||
min_distance = peer_distances[0];
|
||||
|
@ -381,7 +370,7 @@ SST_DoNewRegression(SST_Stats inst)
|
|||
}
|
||||
}
|
||||
|
||||
regression_ok = RGR_FindBestRegression(times_back, inst->offsets, weights,
|
||||
regression_ok = RGR_FindBestRegression(times_back, offsets, weights,
|
||||
inst->n_samples,
|
||||
&est_intercept, &est_slope, &est_var,
|
||||
&est_intercept_sd, &est_slope_sd,
|
||||
|
@ -395,7 +384,7 @@ SST_DoNewRegression(SST_Stats inst)
|
|||
inst->estimated_frequency = est_slope;
|
||||
inst->skew = est_slope_sd * RGR_GetTCoef(degrees_of_freedom);
|
||||
inst->estimated_offset = est_intercept;
|
||||
inst->offset_time = inst->sample_times[inst->n_samples - 1];
|
||||
inst->offset_time = inst->sample_times[inst->last_sample];
|
||||
inst->estimated_offset_sd = est_intercept_sd;
|
||||
inst->variance = est_var;
|
||||
inst->nruns = nruns;
|
||||
|
@ -571,14 +560,15 @@ SST_GetTrackingData(SST_Stats inst, struct timeval *now,
|
|||
void
|
||||
SST_SlewSamples(SST_Stats inst, struct timeval *when, double dfreq, double doffset)
|
||||
{
|
||||
int n, i;
|
||||
int m, n, i;
|
||||
double delta_time;
|
||||
struct timeval *sample, prev;
|
||||
double prev_offset, prev_freq;
|
||||
|
||||
n = inst->n_samples;
|
||||
|
||||
for (i=0; i<n; i++) {
|
||||
for (m = 0; m < n; m++) {
|
||||
i = get_buf_index(inst, m);
|
||||
sample = &(inst->sample_times[i]);
|
||||
prev = *sample;
|
||||
UTI_AdjustTimeval(sample, when, sample, &delta_time, dfreq, doffset);
|
||||
|
@ -615,9 +605,10 @@ SST_SlewSamples(SST_Stats inst, struct timeval *when, double dfreq, double doffs
|
|||
void
|
||||
SST_AddDispersion(SST_Stats inst, double dispersion)
|
||||
{
|
||||
int i;
|
||||
int m, i;
|
||||
|
||||
for (i=0; i < inst->n_samples; i++) {
|
||||
for (m = 0; m < inst->n_samples; m++) {
|
||||
i = get_buf_index(inst, m);
|
||||
inst->root_dispersions[i] += dispersion;
|
||||
inst->peer_dispersions[i] += dispersion;
|
||||
}
|
||||
|
@ -635,7 +626,7 @@ SST_PredictOffset(SST_Stats inst, struct timeval *when)
|
|||
interval is minimal. We can't do any useful prediction other
|
||||
than use the latest sample or zero if we don't have any samples */
|
||||
if (inst->n_samples > 0) {
|
||||
return inst->offsets[inst->n_samples - 1];
|
||||
return inst->offsets[inst->last_sample];
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
|
@ -654,18 +645,12 @@ SST_MinRoundTripDelay(SST_Stats inst)
|
|||
double min_delay, delay;
|
||||
int i;
|
||||
|
||||
if (inst->n_samples == 0) {
|
||||
return DBL_MAX;
|
||||
} else {
|
||||
min_delay = fabs(inst->peer_delays[0]);
|
||||
for (i=1; i<inst->n_samples; i++) {
|
||||
delay = fabs(inst->peer_delays[i]);
|
||||
if (delay < min_delay) {
|
||||
min_delay = delay;
|
||||
}
|
||||
}
|
||||
return min_delay;
|
||||
for (i = 0, min_delay = DBL_MAX; i < inst->n_samples; i++) {
|
||||
delay = fabs(inst->peer_delays[get_buf_index(inst, i)]);
|
||||
if (delay < min_delay)
|
||||
min_delay = delay;
|
||||
}
|
||||
return min_delay;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -675,11 +660,12 @@ SST_MinRoundTripDelay(SST_Stats inst)
|
|||
void
|
||||
SST_SaveToFile(SST_Stats inst, FILE *out)
|
||||
{
|
||||
int i;
|
||||
int m, i;
|
||||
|
||||
fprintf(out, "%d\n", inst->n_samples);
|
||||
|
||||
for(i=0; i<inst->n_samples; i++) {
|
||||
for(m = 0; m < inst->n_samples; m++) {
|
||||
i = get_buf_index(inst, m);
|
||||
|
||||
fprintf(out, "%08lx %08lx %.6e %.6e %.6e %.6e %.6e %.6e %.6e %d\n",
|
||||
(unsigned long) inst->sample_times[i].tv_sec,
|
||||
|
@ -745,6 +731,8 @@ SST_LoadFromFile(SST_Stats inst, FILE *in)
|
|||
return 0;
|
||||
}
|
||||
|
||||
inst->last_sample = inst->n_samples - 1;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
@ -758,7 +746,7 @@ SST_DoSourceReport(SST_Stats inst, RPT_SourceReport *report, struct timeval *now
|
|||
struct timeval ago;
|
||||
|
||||
if (inst->n_samples > 0) {
|
||||
n = inst->n_samples - 1;
|
||||
n = inst->last_sample;
|
||||
report->orig_latest_meas = inst->orig_offsets[n];
|
||||
report->latest_meas = inst->offsets[n];
|
||||
report->latest_meas_err = 0.5*inst->root_delays[n] + inst->root_dispersions[n];
|
||||
|
@ -796,8 +784,9 @@ SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct ti
|
|||
report->n_runs = inst->nruns;
|
||||
|
||||
if (inst->n_samples > 1) {
|
||||
n = inst->n_samples - 1;
|
||||
UTI_DiffTimevalsToDouble(&dspan, &inst->sample_times[n], &inst->sample_times[0]);
|
||||
n = inst->last_sample;
|
||||
UTI_DiffTimevalsToDouble(&dspan, &inst->sample_times[n],
|
||||
&inst->sample_times[get_buf_index(inst, 0)]);
|
||||
report->span_seconds = (unsigned long) (dspan + 0.5);
|
||||
|
||||
if (inst->n_samples > 3) {
|
||||
|
|
Loading…
Reference in a new issue