-
Notifications
You must be signed in to change notification settings - Fork 465
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
storage: round probe timestamps to the probe interval
This commit ensures that probe timestamps, and therefore timestamps used for minting new bindings, are rounded down to the probe interval (typically 1s). This is to reduce the amount of distinct timestamps flowing through a dataflow joining multiple sources. Each distinct timestamp induces some amount of overhead, so forcing the timestamps of individual sources to the same values is more efficient.
- Loading branch information
Showing
6 changed files
with
243 additions
and
92 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright Materialize, Inc. and contributors. All rights reserved. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the LICENSE file. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0. | ||
|
||
//! Support for sending frontier probes to upstream systems. | ||
use std::time::Duration; | ||
|
||
use mz_ore::now::{EpochMillis, NowFn}; | ||
use tracing::trace; | ||
|
||
/// A ticker to drive source upstream probing. | ||
/// | ||
/// This type works similar to [`tokio::time::Interval`] but returns `EpochMillis` timestamps from | ||
/// its [`Ticker::tick`] method that can be used as probe timestamps. These timestamps are rounded | ||
/// down to the nearest multiple of the tick interval, to reduce the amount of unique timestamps | ||
/// emitted by sources, thereby reducing churn in downstream dataflows. | ||
pub(super) struct Ticker { | ||
interval: EpochMillis, | ||
now: NowFn, | ||
last_tick: Option<EpochMillis>, | ||
} | ||
|
||
impl Ticker { | ||
pub fn new(interval: Duration, now: NowFn) -> Self { | ||
let interval = interval.as_millis().try_into().unwrap(); | ||
Self { | ||
interval, | ||
now, | ||
last_tick: None, | ||
} | ||
} | ||
|
||
/// Wait until it is time for the next probe, returning a suitable probe timestamp. | ||
/// | ||
/// This method tries to resolve as close as possible to the returned probe timestamp, though | ||
/// it is not guaranteed to always succeed. If a tick is missed, it is skipped entirely. | ||
pub async fn tick(&mut self) -> EpochMillis { | ||
let mut now = (self.now)(); | ||
|
||
let target = match self.last_tick { | ||
Some(ms) => ms + self.interval, | ||
None => now, | ||
}; | ||
let target = self.round_to_interval(target); | ||
|
||
while now < target { | ||
let wait = Duration::from_millis(target - now); | ||
tokio::time::sleep(wait).await; | ||
now = (self.now)(); | ||
} | ||
|
||
trace!(target, now, "probe ticker skew: {}ms", now - target); | ||
|
||
let this_tick = self.round_to_interval(now); | ||
self.last_tick = Some(this_tick); | ||
this_tick | ||
} | ||
|
||
fn round_to_interval(&self, ms: EpochMillis) -> EpochMillis { | ||
ms - (ms % self.interval) | ||
} | ||
} |
Oops, something went wrong.