Timing accuracy: NTP/PTP-over-Wi-Fi comparison + USB-vs-PCIe transport-latency bench#228
Merged
Conversation
… vs PCIe MMIO) One binary that times RtlAdapter::rtw_read32 in a tight loop over whichever transport it opens — USB vendor-control by default, PCIe BAR2 MMIO when DEVOURER_PCIE_BDF is set (the PCIe path compiles only with DEVOURER_PCIE, via the devourer PUBLIC DEVOURER_HAVE_PCIE define). Same call on both buses = a fair comparison of the per-op latency + jitter that bound AdjustBeaconTimingFine (a TSF read-modify-write) and hence the closed-loop uplink timing advance. Measured on the bench (same reglat.cpp): USB 8822EU mean ~68 us/op jitter(p99-p50) ~64 us PCIe 8821CE MMIO mean ~2.2 us/op jitter ~0.08 us => PCIe ~30x faster, ~600-900x lower jitter — quantifies why the USB actuator jitter (~5-7 chained ops -> ~0.5-1.2 ms) would collapse to ~us on a PCIe MMIO path, i.e. the USB transport, not the sync method, is the closed-loop TA floor. Added as a plain add_executable (built in all configs; USB path only when PCIE is off). No library change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…/PCIe latency Answer the recurring "how accurate vs NTP/PTP over Wi-Fi?" question with measured numbers from a two-node bench, methodology, and honest caveats: - NTP (chrony, software timestamps): ~0.76 ms RMS on a quiet link, tens of ms under Wi-Fi power-save/contention. - PTP (ptp4l): does not run — neither the in-tree nor the reference/ vendor drivers expose the hardware timestamp to the kernel timestamping API (ethtool -T: none), though both read the TSF internally. - devourer TSF downlink: ~0.25 us RMS residual — the MAC latches the timestamp below the CSMA/queue/power-save layer whose RTT jitter (measured 1.6->110 ms under load) bounds NTP/PTP. ~3000x tighter, and the reason PTP can't run. - Transport: reglat shows USB ~68 us/op vs PCIe MMIO ~2.2 us/op (jitter ~64 vs ~0.08 us) — the actuator/uplink-TA floor is the transport, not the method. Caveats kept explicit: devourer's number is one-way relative precision (TSF is 1 us resolution, sub-us via averaging), NTP's is the healthy-link daemon offset, and FTM ranging can beat a one-way TSF on absolute accuracy. Indexed in README. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
libusb.h pulls in <windows.h>, which defines a max() macro, so std::max(...) fails to compile under MSVC (C2589). Clamp the sample count manually instead. No behavior change; GCC/Clang unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Answers the recurring question "how accurate is the TSF time distribution vs NTP/PTP
over Wi-Fi?" with measured numbers from a two-node bench, and lands a reusable
transport-latency microbench. Follow-up to #227 (over-the-air time distribution).
Two small, self-contained additions — a benchmark tool and a docs writeup; no
library change.
tests/reglat.cpp— register round-trip latency (USB vs PCIe)One binary that times
RtlAdapter::rtw_read32over whichever transport it opens —USB vendor-control by default, PCIe BAR2 MMIO when
DEVOURER_PCIE_BDFis set (thePCIe path compiles only with
DEVOURER_PCIE, via thedevourerPUBLICDEVOURER_HAVE_PCIEdefine). Added as a plainadd_executable(USB path builds inall configs). Measured on the same binary:
→ ~30× faster, ~600–900× lower jitter. The
AdjustBeaconTimingFineactuatorchains ~5–7 register ops, so the ~0.5–1.2 ms USB jitter (and the ~1.3 ms closed-loop
uplink-TA residual) is a transport floor — a PCIe MMIO path would collapse it
toward µs.
docs/timing-accuracy.md— NTP / PTP over Wi-Fi vs TSFMeasured on two machines associated to the same AP:
chrony -Q, software TS)ptp4l)CSMA/queue/power-save layer whose RTT jitter (measured 1.6 → 110 ms under
load) bounds software-timestamped protocols.
ethtool -T=PTP Hardware Clock: none; grepping thereference/vendor drivers forSOF_TIMESTAMPING/SIOCSHWTSTAMP/skb_hwtstamps/get_ts_infofinds nothing — neither vendor nor in-tree driver exposes the HWtimestamp to the kernel API, though both read the TSF internally. devourer
surfaces it (
RxPacket.tsfl), which is what enables sub-µs sync.Caveats kept explicit in the doc: devourer's figure is one-way relative precision
(TSF is 1 µs resolution, sub-µs via averaging), NTP's is the healthy-link daemon
offset, and FTM ranging can beat a one-way TSF on absolute accuracy.
Testing
ctestgreen; multi-config build clean (reglatbuilds in USB-only and PCIeconfigs); PCIe path verified on a Radxa X4 (RTL8821CE) via vfio-pci.
🤖 Generated with Claude Code