Files
SonicForgeStudio/native_bridge/debug/G0_RESULTS.md

6.4 KiB
Raw Permalink Blame History

G0 — Baseline đo latency (kết quả)

Ngày: 2026-08-27. Probe: native_bridge/debug/g0_latency_probe.py (chạy với timeBeginPeriod(1), 10k block/config, pipeline thật Python→SHM→fx_vst_bridge→SHM). Log: native_bridge/debug/g0_probe_run_full.log (run 1), native_bridge/debug/g0_probe_run2.log (run 2 — có pump_rate + drain đầy đủ).

1. Bảng latency plugin (getLatencySamples, @48kHz)

Plugin getLatencySamples ms @48k Ghi chú
Sonible pureComp 2108 43.9 báo latency thật (lookahead)
iZotope Ozone 11 0 0 không báo latency (realtime mode)
empty (passthrough) — — chain rỗng

Nguồn: probe plugin_latency + log app thật fxrt_bridge.log ([RenderFx] STEP getLatencySamples = 2108/0).

2. Jitter round-trip (10k block, 53.3s/config)

Round-trip = thời gian từ lúc probe gọi write_input(block j) đến lúc nhận read_output() block j (FIFO theo index). Đã sửa pacing probe bằng timeBeginPeriod(1) (bridge C++ đã gọi — RealtimeFxLoop.cpp:160); lần chạy trước thiếu nó → Sleep 15.6ms granularity → pump ~22ms/batch ≠ 21.33ms realtime → pureComp bị "stall 1.9s" giả. Với pacing chuẩn, stall đó biến mất — là artifact probe, KHÔNG phải VST stall.

Config mean ms σ p50 p99 max recv/sent pump_rate drained
empty 21.67 0.88 21.70 22.03 26.51 10000/10000 184.8 ✅
pureComp 21.69 0.15 21.67 22.03 24.07 10000/10000 184.9 ✅
Ozone 11 21.70 0.14 21.68 22.02 22.20 10000/10000 184.8 ✅
  • Round-trip ≈ 21.5–21.7ms = đúng 1 batch 4 block (21.33ms) + overhead nhỏ (SHM copy + bridge proc 0.001–0.45ms). Latency plugin KHÔNG nằm trong round-trip — plugin latency bù bằng PDC (không chặn pipeline).
  • drained=True mọi config (run 2): bridge xử lí HẾT 10000 block, recv = sent — KHÔNG mất block, KHÔNG backlog tích lũy. Đây là bằng chứng quyết định: không có drift thật (xem §4).
  • σ round-trip: 0.14–0.15ms (pureComp/Ozone) — RẤT nhỏ → Gate G2 MỞ: PDC mẫu có ý nghĩa, không cần giảm jitter trước (không cần relay WS→SHM sớm).
  • empty σ=0.88: 1 outlier khởi động (min=0.05ms), p50/p99 vẫn 21.7/22.0.

3. Inter-arrival deviation

Config σ ms min max
empty 9.44 −5.33 38.4
pureComp 9.36 −5.33 23.5
Ozone 11 9.36 −5.33 17.8

Block về theo batch 4 (bridge xử lí take=4/lần) → inter-arrival lệch so với 5.33ms lý tưởng là đặc tính batching, không phải jitter ngẫu nhiên. Round-trip σ (§2) là thước đo đúng cho PDC; inter-arrival dùng cho sizing FILL — xem §5.

4. Bridge FxRTPerf

Nguồn procAvg procMax loopAvg loopMax rate blk/s vs realtime 187.5
probe empty 0.001ms 0.06ms 22.0ms 1017ms 181.5 −3.2%
probe pureComp 0.46ms 1.37ms 22.0ms 1011ms 181.6 −3.1%
probe Ozone 0.14ms 0.71ms 22.0ms 1015ms 181.5 −3.2%
app thật (master chain đầy) 3.4ms 10.0ms 21.4ms 156ms 186.5 −0.5%
  • Rate "chậm 3% (probe) / 0.5% (app)" KHÔNG phải drift thật — artifact đo. Bằng chứng: run 2 drained=True, recv=sent=10000 mọi config — nếu bridge thật sự chậm 3%, backlog 300+ block phải tích lại và drain phải mất >1.5s sau pump (thực tế drain xong ngay trong vòng lặp pump, pump_rate chỉ thấp vì probe tự sleep lệch pha với nhịp bridge poll 1ms + granularity sleep). Bridge xử lí ASAP khi có input (avail>0 → process ngay) — không có pace riêng để "chậm"; output rate = input rate. App thật rate 186.5 thấp hơn vì runSec gồm idle trước khi audio chảy (chain load, chờ play).
  • loopMax ≈ 1s ở MỌI config probe kể cả empty — spike 1s/lần chạy ~53s, không phải VST (empty cũng có). Không xuất hiện trong log app thật gần nhất (loopMax 156ms) — nghi Windows scheduler/antivirus/power, cần theo dõi khi chạy thật. Probe round-trip max vẫn ≤27ms → spike xảy ra lúc bridge idle, không chặn block đang xử lí (không gây underrun).
  • Kết luận: KHÔNG cần bù drift. FILL 8 block + underrun-fade/resume hiện có đủ — u=3/session (fx_stats) hiếm, do main-thread stall (GUI), không phải drift đều. Đề xuất resync/bù rate ban đầu rút lại (xem §6).

5. ~0.22s gồm gì (xác nhận)

Latency path thực đo + hằng số app:

Thành phần ms Nguồn
Batching 4 block (pipeline) ~21.6 probe round-trip (§2)
FILL buffer worklet 8 block 42.7 sf-fx-realtime.js FILL=8
Plugin latency (pureComp) 43.9 getLatencySamples=2108 @48k
WS/main-thread jitter (warm, p50) ~101 dbg.log fx_play_first sincePlay 38–160ms
Tổng nghe thấy (warm) ~210ms ≈ 0.21s khớp ~0.22s quan sát
  • PDC hiện tại FX_RT_ROUNDTRIP_SAMPLES=3840 (80ms) = batching ~7 block + FILL 8 block — khớp thực đo (21.6 + 42.7 ≈ 64ms + WS jitter margin). Giữ nguyên; latencyTotal (plugin thật qua {cmd:'latency'}) cộng thêm đúng (pureComp +43.9ms).
  • Cold start VST load: 8–17s (dbg.log sincePlay 8111–17211ms), warm sau đó 38–160ms — là plugin init, không phải latency pipeline; không nằm trong PDC.
  • fx_stats app thật (session master): u=3 h=3 f=13 s=13 cap=1 fi=13 q=5–11 — underrun hiếm, queue duy trì 5–11 block → FILL đủ hấp thụ jitter thường.

6. Kết luận cho G2+

  1. Gate G2: MỞ. σ round-trip 0.14–0.15ms → PDC mẫu có nghĩa; không cần relay WS→SHM trước G2.
  2. Không có drift bridge (đã kiểm chứng run 2: drained=True, recv=sent). Không cần bù rate/resync — FILL 8 + underrun-fade/resume đủ. Tránh thêm code không cần thiết. Nếu sau này thấy underrun đều trên session dài → đo lại pump_rate/drained trước khi kết luận drift.
  3. loopMax ~1s spike (probe, cả empty): theo dõi, chưa thấy ở app thật.
  4. Plugin latency bảng §1 đủ cho G2: graph.getLatencySamples() sẽ thay hằng số; dữ liệu hiện tại xác nhận pureComp là plugin duy nhất có latency thật.