fix(fxrt): chan out ring overflow trong bridge (backpressure, het pointer collision)

This commit is contained in:
2026-08-24 12:25:14 +07:00
parent 09d8a386fb
commit e12a8d754a
3 changed files with 18 additions and 2 deletions
+18 -2
View File
@@ -205,7 +205,7 @@ int run_realtime_fx_loop(const std::string& jobPath, const std::string& shmName,
uint64_t processed = 0;
uint64_t lastGen = 0; // chain generation đã báo latency
// ---- FXRT_PERF instrumentation (tạm, đo crackle) ----
uint64_t perfIter = 0, perfProc = 0, perfIdle = 0;
uint64_t perfIter = 0, perfProc = 0, perfIdle = 0, perfOutFull = 0;
double perfProcSum = 0.0, perfProcMax = 0.0, perfProcMin = 1e9;
double perfLoopSum = 0.0, perfLoopMax = 0.0;
uint32_t perfTakeSum = 0;
@@ -264,6 +264,21 @@ int run_realtime_fx_loop(const std::string& jobPath, const std::string& shmName,
std::cerr << "[RealtimeFxLoop] latency reported: " << lats.size()
<< " slot(s)" << std::endl;
}
// OUT-ring backpressure (fix crackle "wobble" — pointer collision):
// kiểm tra chỗ trống TRƯỚC khi consume input. Nếu out ring đầy (engine
// pump chậm/stall: WS send bị block khi main-thread browser busy) mà
// bridge vẫn ghi → ghi đè slot engine đang đọc = read/write pointer
// giẫm nhau → mẫu torn → méo "wobble" kéo dài tới khi reset. Khi đầy:
// KHÔNG xử lí batch này (nhường engine drain), input backlog dồn về
// engine → engine drop batch cũ nhất (drop sạch, worklet hold+fade che
// gap) — không bao giờ ghi đè out slot chưa đọc.
const uint32_t outFree = ipc->h.outSlots - (ipc->h.outWrite - ipc->h.outRead);
if (outFree < std::min<uint32_t>(ipc->h.inWrite - ipc->h.inRead, FXRT_IN_SLOTS)) {
++perfOutFull;
std::this_thread::sleep_until(std::chrono::steady_clock::now() +
std::chrono::milliseconds(1));
continue;
}
uint32_t avail = ipc->h.inWrite - ipc->h.inRead;
if (avail == 0) {
++perfIdle;
@@ -315,12 +330,13 @@ int run_realtime_fx_loop(const std::string& jobPath, const std::string& shmName,
<< " loopAvg=" << (perfIter ? perfLoopSum / perfIter : 0.0) << "ms"
<< " loopMax=" << perfLoopMax << "ms"
<< " idle=" << perfIdle
<< " outFull=" << perfOutFull
<< " takeAvg=" << (perfProc ? (double)perfTakeSum / perfProc : 0.0)
<< " procBlocks=" << processed
<< " rate=" << (runSec > 0 ? processed / runSec : 0.0) << "blk/s"
<< " outDepth=" << (ipc->h.outWrite - ipc->h.outRead)
<< std::endl;
perfProc = 0; perfProcSum = 0.0; perfTakeSum = 0; perfIdle = 0;
perfProc = 0; perfProcSum = 0.0; perfTakeSum = 0; perfIdle = 0; perfOutFull = 0;
}
}
ipc->h.state = FXRT_STATE_STARTING; // đã dừng
Binary file not shown.