MP: peer shakiness ROOT-CAUSED as single-box packet jitter (rig, not game) + affinity launcher (task #50)
The residual RANDOM peer shakiness on accel/decel was proven (BT_RXJIT record inter-arrival probe) to be TEST-RIG packet jitter, not the game: two Debug btl4 nodes on one box contend for CPU, so Windows batches their TCP delivery -- records arrive in bursts (max 56-226ms gaps, burstiness 3-7x) instead of even ~17ms. The peer dead-reckons across the gaps then snaps -> random shake. Pinning the nodes to disjoint cores restored even ~17ms delivery (burstiness ~1.0) and the shakiness vanished (user-confirmed 'that was it'). Real pods = dedicated machines, no contention -> never see it. So NO un-authentic jitter buffer -- the coupled body-channel peer (96a896a/f094d78/23f1532) is the authentic + correct finish. - mech.cpp: BT_RXJIT record-arrival-jitter probe (env-gated). - tools/mp_launch.sh: 2-node launcher that pins nodes to disjoint cores (bakes in the fair-delivery condition; documents why). - context/multiplayer.md: the finding, so it is not re-litigated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
23f1532fb0
commit
49d73dc8e2
@@ -1790,6 +1790,33 @@ Logical
|
||||
void
|
||||
Mech::ReadUpdateRecord(Simulation::UpdateRecord *message)
|
||||
{
|
||||
// RECORD-CADENCE probe (BT_RXJIT): quantify how EVENLY records arrive (wall-clock
|
||||
// ms between arrivals) -- the jitter that makes the peer's corrections random.
|
||||
if (getenv("BT_RXJIT") && GetInstance() == ReplicantInstance)
|
||||
{
|
||||
LARGE_INTEGER _now, _freq;
|
||||
QueryPerformanceCounter(&_now); QueryPerformanceFrequency(&_freq);
|
||||
static double s_lastMs = 0.0, s_min = 1e9, s_max = 0.0, s_acc = 0.0;
|
||||
static int s_n = 0, s_rep = 0;
|
||||
const double nowMs = (double)_now.QuadPart * 1000.0 / (double)_freq.QuadPart;
|
||||
if (s_lastMs > 0.0)
|
||||
{
|
||||
const double gap = nowMs - s_lastMs;
|
||||
s_n++; s_acc += gap;
|
||||
if (gap > s_max) s_max = gap;
|
||||
if (gap < s_min) s_min = gap;
|
||||
}
|
||||
s_lastMs = nowMs;
|
||||
if (++s_rep >= 120 && s_n > 0)
|
||||
{
|
||||
DEBUG_STREAM << "[rxjit] records/win=" << s_n
|
||||
<< " gapMs min=" << s_min << " avg=" << (s_acc / s_n)
|
||||
<< " max=" << s_max
|
||||
<< " burstiness(max/avg)=" << (s_max / (s_acc / s_n))
|
||||
<< "\n" << std::flush;
|
||||
s_rep = 0; s_n = 0; s_acc = 0.0; s_min = 1e9; s_max = 0.0;
|
||||
}
|
||||
}
|
||||
static const int s_mrecLog = getenv("BT_REPL_LOG") ? 1 : 0;
|
||||
if (s_mrecLog && message->recordID != 0)
|
||||
DEBUG_STREAM << "[mrec-rx] type=" << (int)message->recordID
|
||||
|
||||
Reference in New Issue
Block a user