diff --git a/MUNGA/MOVER.cpp b/MUNGA/MOVER.cpp index 5f260e6..7e2f809 100644 --- a/MUNGA/MOVER.cpp +++ b/MUNGA/MOVER.cpp @@ -47,6 +47,14 @@ static const Scalar kMinimumPredictedInterval = 0.010f; // static const Scalar kMaximumPredictedInterval = 0.25f; +// +// A gap this long is a stall, not jitter - six times the observed rate. +// A gap this short cannot be a sender keeping to 30ms, so it is a packet +// that was already waiting when we finally got round to reading it. +// +static const Scalar kLongGapThreshold = 0.200f; +static const Scalar kQueuedGapThreshold = 0.005f; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // RP412NETPREDICT=0 restores the original single-sample prediction, so the @@ -745,7 +753,21 @@ void << "m, predicting " << predictedInterval << "s worst miss " << worst_error << "s\n" << std::flush; + + DEBUG_STREAM << "CamLog: replicant arrivals - widest gap " + << widestGap << "s, " << longGapCount + << " long, " << queuedGapCount + << " queued (" + << ((longGapCount > 0 && queuedGapCount > 0) + ? "our loop stalled" + : (longGapCount > 0 + ? "sender went quiet" + : "clean")) + << ")\n" << std::flush; } + widestGap = 0.0f; + longGapCount = 0; + queuedGapCount = 0; next_say = ((Scalar) Now()) + 5.0f; steps = 0; spikes = 0; @@ -1025,6 +1047,14 @@ void } predictedInterval = predicted; + // + // Arrival statistics, for telling a quiet sender from + // our own stalled loop. See the members. + // + if (diff > widestGap) { widestGap = diff; } + if (diff > kLongGapThreshold) { longGapCount++; } + if (diff < kQueuedGapThreshold) { queuedGapCount++; } + nextUpdate += predicted; } else @@ -2061,6 +2091,9 @@ Mover::Mover( ResetUpdateIntervals(); predictedInterval = 0.0f; predictionError = 0.0f; + widestGap = 0.0f; + longGapCount = 0; + queuedGapCount = 0; normalizeCount = 0; if (IsInitialStasis()) diff --git a/MUNGA/MOVER.h b/MUNGA/MOVER.h index d193c80..53cb685 100644 --- a/MUNGA/MOVER.h +++ b/MUNGA/MOVER.h @@ -311,6 +311,19 @@ protected: predictedInterval, predictionError; + // + // Arrival statistics for the window a trace reports over. A long gap + // followed by normal gaps means the sender went quiet; a long gap + // followed by a burst of near-zero ones means OUR loop stalled and the + // packets queued up behind it. The two look identical from inside the + // dead reckoner and want opposite fixes. + // + Scalar + widestGap; + int + longGapCount, + queuedGapCount; + Scalar PredictUpdateInterval(Scalar latest); void