#include "TimeBase.h" #include namespace udpscope { /* UDPS_T_UINT64 == 6 in Common/UDP/UDPSProtocol.h. Spelled numerically so this * translation unit stays free of the C client header. */ static constexpr uint8_t kTypeUint64 = 6u; double TimeSignalScale(uint8_t typeCode) { return (typeCode == kTypeUint64) ? 1.0e-9 : 1.0e-6; } double ClockOffset::map(double producerSec, double wallSec) { /* Symmetric on purpose. Delivery jitter of a few tens of ms either side of * the prediction must not reset the offset or the whole trace wobbles, but a * producer clock that steps in EITHER direction has to be picked up: a * restart leaves the prediction behind the wall clock, an NTP correction on * the producer's host leaves it ahead. A one-sided test silently never fires * for the second case and the trace sits in the future for the whole run. */ if (!valid_ || std::fabs(wallSec - (offset_ + producerSec)) > kRecalibThresholdS) { offset_ = wallSec - producerSec; valid_ = true; } return offset_ + producerSec; } void HrtRateFit::reset() { samples_.clear(); n_ = 0; rate_ = 0.0; } void HrtRateFit::add(uint64_t hrt, double wallSec) { samples_.push_back(Sample{static_cast(hrt), wallSec}); if (samples_.size() > kWindow) { samples_.pop_front(); } n_++; if (n_ >= kMinSamples) { refit(); } } void HrtRateFit::refit() { const size_t n = samples_.size(); if (n < 2) { return; } /* Least squares slope of hrt against wall time. Both are subtracted from * their first value first: raw hrt counts and epoch seconds are large * enough that the naive sums lose precision. */ const double h0 = samples_.front().hrt; const double w0 = samples_.front().wall; double sw = 0.0, sh = 0.0, sww = 0.0, swh = 0.0; for (const Sample& s : samples_) { const double w = s.wall - w0; const double h = s.hrt - h0; sw += w; sh += h; sww += w * w; swh += w * h; } const double dn = static_cast(n); const double denom = dn * sww - sw * sw; if (std::fabs(denom) < 1e-12) { return; } const double slope = (dn * swh - sw * sh) / denom; if (slope > 0.0 && std::isfinite(slope)) { rate_ = slope; } } double HrtRateFit::toSeconds(uint64_t hrt) const { if (rate_ <= 0.0) { return 0.0; } return static_cast(hrt) / rate_; } } /* namespace udpscope */