namespace MoShiro.Measurement;
/// 节点的单调时钟(微秒):t1…t4、t_send、t_recv 都用它;Probe 和 Agent 各自一个,块头里的时钟锚点把它对应到 UTC。
public sealed class MonoClock
{
private readonly TimeProvider _time;
public MonoClock(TimeProvider time)
{
_time = time;
}
public TimeProvider Time => _time;
public long NowUs()
{
long ticks = _time.GetTimestamp();
// 先除后乘会丢精度,先乘再除在 64 位内不会溢出(频率通常是 1e9 或 1e7)
return (ticks / _time.TimestampFrequency * 1_000_000) + (ticks % _time.TimestampFrequency * 1_000_000 / _time.TimestampFrequency);
}
public ClockAnchor Anchor() => new(NowUs(), _time.GetUtcNow().ToUnixTimeMilliseconds());
/// 单调时钟读数 对应的 UTC 毫秒(只用于块的粗略起点,精确时间由块头的时钟锚点换算)。
public long UtcMsAt(long thenUs) => _time.GetUtcNow().ToUnixTimeMilliseconds() - (Math.Max(0, NowUs() - thenUs) / 1000);
}