#![expect(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
reason = "metric reporting casts counters and nanosecond values to floating point for human-readable output; precision loss there is irrelevant"
)]
use std::fmt::Debug;
use std::num::{NonZeroU32, NonZeroUsize};
use std::process::ExitCode;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::time::{Duration, Instant};
use std::{env, hint, iter, mem};
use futures::stream::{self, StreamExt};
use ratatui::Terminal;
use ratatui::backend::TestBackend;
use tears::command::CommandId;
use tears::prelude::*;
use tears::{BoxStream, RuntimeConfig, SubscriptionSource};
use tokio::runtime::{Builder, Runtime as TokioRuntime};
use tokio::task::yield_now;
use tokio::time::{MissedTickBehavior, interval, timeout};
use tokio_stream::wrappers::IntervalStream;
use tracing::field::{Field, Visit};
use tracing::level_filters::LevelFilter;
use tracing::span::{Attributes, Id, Record};
use tracing::subscriber::set_global_default;
use tracing::{Event, Level, Metadata, Subscriber};
const BURST: u64 = 0;
fn frame_rate() -> FrameRate {
FrameRate::new(NonZeroU32::new(60).expect("non-zero fps"))
.expect("60 FPS is a valid frame rate")
}
const APP_CHANNEL_CAPACITY: usize = 1024;
const KEYED_CHANNEL_CAPACITY: usize = 16;
fn bounded_config() -> RuntimeConfig {
RuntimeConfig::new(frame_rate())
.app_channel_capacity(NonZeroUsize::new(APP_CHANNEL_CAPACITY).expect("non-zero"))
.keyed_channel_capacity(NonZeroUsize::new(KEYED_CHANNEL_CAPACITY).expect("non-zero"))
}
#[derive(Clone, Copy, PartialEq, Eq)]
enum Mode {
Default,
Bounded,
}
impl Mode {
fn build_runtime(self, flags: (ScenarioCfg, Arc<Metrics>)) -> Runtime<LoadApp> {
match self {
Self::Default => Runtime::new(flags, frame_rate()),
Self::Bounded => Runtime::with_config(flags, bounded_config()),
}
}
}
#[derive(Clone)]
struct ScenarioCfg {
name: &'static str,
rate: u64,
total: u64,
update_cost: Duration,
render_cost: Duration,
keyed_probe: bool,
quit_at_seq: Option<u64>,
keyed_quit: bool,
mode: Mode,
producers: u32,
max_wall: Duration,
}
#[derive(Clone, Copy)]
enum ValidTrial {
Always,
BlockedEq(u64),
BlockedAtLeast(u64),
Churn,
}
impl ValidTrial {
fn holds(self, metrics: &Metrics) -> bool {
match self {
Self::Always => true,
Self::BlockedEq(n) => metrics.blocked_at_quit.load(Ordering::Relaxed) == n,
Self::BlockedAtLeast(n) => metrics.blocked_at_quit.load(Ordering::Relaxed) >= n,
Self::Churn => metrics.capacity_waits_before_quit.load(Ordering::Relaxed) >= 2,
}
}
}
struct QuitScenarioCfg {
base: ScenarioCfg,
trials: u32,
valid_trial: ValidTrial,
}
#[expect(clippy::too_many_lines, reason = "a flat table of scenario literals")]
fn scenarios() -> Vec<ScenarioCfg> {
vec![
ScenarioCfg {
name: "steady_20k",
rate: 20_000,
total: 100_000,
update_cost: Duration::from_micros(2),
render_cost: Duration::from_micros(500),
keyed_probe: false,
quit_at_seq: None,
keyed_quit: false,
producers: 1,
mode: Mode::Default,
max_wall: Duration::from_secs(30),
},
ScenarioCfg {
name: "steady_200k",
rate: 200_000,
total: 1_000_000,
update_cost: Duration::from_micros(2),
render_cost: Duration::from_micros(500),
keyed_probe: false,
quit_at_seq: None,
keyed_quit: false,
producers: 1,
mode: Mode::Default,
max_wall: Duration::from_secs(30),
},
ScenarioCfg {
name: "burst_200k",
rate: BURST,
total: 200_000,
update_cost: Duration::from_micros(2),
render_cost: Duration::from_micros(500),
keyed_probe: false,
quit_at_seq: None,
keyed_quit: false,
producers: 1,
mode: Mode::Default,
max_wall: Duration::from_secs(30),
},
ScenarioCfg {
name: "overload",
rate: 100_000,
total: 500_000,
update_cost: Duration::from_micros(25),
render_cost: Duration::from_micros(500),
keyed_probe: false,
quit_at_seq: None,
keyed_quit: false,
producers: 1,
mode: Mode::Default,
max_wall: Duration::from_secs(60),
},
ScenarioCfg {
name: "keyed_steady",
rate: 20_000,
total: 100_000,
update_cost: Duration::from_micros(2),
render_cost: Duration::from_micros(500),
keyed_probe: true,
quit_at_seq: None,
keyed_quit: false,
producers: 1,
mode: Mode::Default,
max_wall: Duration::from_secs(30),
},
ScenarioCfg {
name: "keyed_overload",
rate: 100_000,
total: 500_000,
update_cost: Duration::from_micros(25),
render_cost: Duration::from_micros(500),
keyed_probe: true,
quit_at_seq: None,
keyed_quit: false,
producers: 1,
mode: Mode::Default,
max_wall: Duration::from_secs(60),
},
ScenarioCfg {
name: "burst_200k_bounded",
rate: BURST,
total: 200_000,
update_cost: Duration::from_micros(2),
render_cost: Duration::from_micros(500),
keyed_probe: false,
quit_at_seq: None,
keyed_quit: false,
producers: 1,
mode: Mode::Bounded,
max_wall: Duration::from_secs(30),
},
ScenarioCfg {
name: "overload_bounded",
rate: 100_000,
total: 500_000,
update_cost: Duration::from_micros(25),
render_cost: Duration::from_micros(500),
keyed_probe: false,
quit_at_seq: None,
keyed_quit: false,
producers: 1,
mode: Mode::Bounded,
max_wall: Duration::from_secs(60),
},
ScenarioCfg {
name: "keyed_overload_bounded",
rate: 100_000,
total: 500_000,
update_cost: Duration::from_micros(25),
render_cost: Duration::from_micros(500),
keyed_probe: true,
quit_at_seq: None,
keyed_quit: false,
producers: 1,
mode: Mode::Bounded,
max_wall: Duration::from_secs(60),
},
]
}
const QUIT_TRIALS: u32 = 200;
const KEYED_QUIT_TRIALS: u32 = 20;
#[expect(clippy::too_many_lines, reason = "a flat table of scenario literals")]
fn quit_scenarios() -> Vec<QuitScenarioCfg> {
let base = ScenarioCfg {
name: "",
rate: BURST,
total: 0,
update_cost: Duration::from_micros(25),
render_cost: Duration::from_micros(500),
keyed_probe: false,
quit_at_seq: Some(5_000),
keyed_quit: false,
producers: 1,
mode: Mode::Default,
max_wall: Duration::from_secs(30),
};
vec![
QuitScenarioCfg {
base: ScenarioCfg {
name: "quit_idle",
total: 1,
quit_at_seq: Some(0),
..base.clone()
},
trials: QUIT_TRIALS,
valid_trial: ValidTrial::Always,
},
QuitScenarioCfg {
base: ScenarioCfg {
name: "quit_backlog_50k",
total: 55_000,
..base.clone()
},
trials: QUIT_TRIALS,
valid_trial: ValidTrial::Always,
},
QuitScenarioCfg {
base: ScenarioCfg {
name: "quit_backlog_300k",
total: 305_000,
..base.clone()
},
trials: QUIT_TRIALS,
valid_trial: ValidTrial::Always,
},
QuitScenarioCfg {
base: ScenarioCfg {
name: "quit_overload",
rate: 100_000,
total: 500_000,
..base.clone()
},
trials: QUIT_TRIALS,
valid_trial: ValidTrial::Always,
},
QuitScenarioCfg {
base: ScenarioCfg {
name: "quit_keyed_backlog_50k",
total: 55_000,
keyed_quit: true,
..base.clone()
},
trials: KEYED_QUIT_TRIALS,
valid_trial: ValidTrial::Always,
},
QuitScenarioCfg {
base: ScenarioCfg {
name: "quit_idle_bounded",
total: 1,
quit_at_seq: Some(0),
mode: Mode::Bounded,
..base.clone()
},
trials: QUIT_TRIALS,
valid_trial: ValidTrial::Always,
},
QuitScenarioCfg {
base: ScenarioCfg {
name: "quit_blocked_1",
total: 500_000,
mode: Mode::Bounded,
..base.clone()
},
trials: QUIT_TRIALS,
valid_trial: ValidTrial::BlockedEq(1),
},
QuitScenarioCfg {
base: ScenarioCfg {
name: "quit_blocked_64",
total: 500_000,
producers: 64,
mode: Mode::Bounded,
..base.clone()
},
trials: QUIT_TRIALS,
valid_trial: ValidTrial::BlockedEq(64),
},
QuitScenarioCfg {
base: ScenarioCfg {
name: "quit_overload_bounded",
rate: 100_000,
total: 500_000,
mode: Mode::Bounded,
..base.clone()
},
trials: QUIT_TRIALS,
valid_trial: ValidTrial::Churn,
},
QuitScenarioCfg {
base: ScenarioCfg {
name: "quit_keyed_bounded",
total: 500_000,
keyed_quit: true,
mode: Mode::Bounded,
..base
},
trials: KEYED_QUIT_TRIALS,
valid_trial: ValidTrial::BlockedAtLeast(1),
},
]
}
static TRIAL_METRICS: Mutex<Option<Arc<Metrics>>> = Mutex::new(None);
static LIVE_PRODUCERS: AtomicU64 = AtomicU64::new(0);
static GAUGE_SEQ_SEEN: Mutex<u64> = Mutex::new(0);
async fn await_quiescence() {
let quiesced = timeout(Duration::from_secs(5), async {
while LIVE_PRODUCERS.load(Ordering::Relaxed) != 0 {
yield_now().await;
}
})
.await;
assert!(
quiesced.is_ok(),
"harness fault: a scenario's producers did not quiesce within 5s; \
refusing to reuse the trial slot with a teardown still in flight",
);
*GAUGE_SEQ_SEEN
.lock()
.expect("gauge seq high-water mark poisoned") = 0;
}
struct QuitDeliverySubscriber;
impl Subscriber for QuitDeliverySubscriber {
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
metadata.is_event()
&& *metadata.level() == Level::DEBUG
&& matches!(metadata.target(), "tears::runtime" | "tears::runtime::load")
}
fn max_level_hint(&self) -> Option<LevelFilter> {
Some(LevelFilter::DEBUG)
}
fn new_span(&self, _span: &Attributes<'_>) -> Id {
Id::from_u64(1)
}
fn record(&self, _span: &Id, _values: &Record<'_>) {}
fn record_follows_from(&self, _span: &Id, _follows: &Id) {}
#[expect(
clippy::significant_drop_tightening,
reason = "the gauge high-water guard is deliberately held across the value stores so \"advance and apply\" is one step; tightening it would let a concurrent stale gauge event interleave a store between the check and the apply (RFC 0006 §4.4)"
)]
fn event(&self, event: &Event<'_>) {
let is_load = event.metadata().target() == "tears::runtime::load";
let mut visitor = LoadVisitor::default();
event.record(&mut visitor);
if is_load && let Some(seq) = visitor.seq {
let slot = TRIAL_METRICS
.lock()
.expect("trial metrics slot poisoned")
.clone();
let mut seen = GAUGE_SEQ_SEEN
.lock()
.expect("gauge seq high-water mark poisoned");
if seq <= *seen {
return;
}
*seen = seq;
LIVE_PRODUCERS.store(visitor.gauge_sum(), Ordering::Relaxed);
if let (Some(metrics), Some(blocked)) = (slot, visitor.blocked) {
metrics.blocked_live.store(blocked, Ordering::Relaxed);
}
return;
}
let Some(metrics) = TRIAL_METRICS
.lock()
.expect("trial metrics slot poisoned")
.clone()
else {
return;
};
if is_load {
if visitor.channel.as_deref() == Some("shared") {
metrics
.capacity_wait_shared_ns
.lock()
.expect("capacity-wait log poisoned")
.push(metrics.elapsed_ns());
}
} else if visitor.matched_quit {
metrics
.quit_delivered_ns
.store(metrics.elapsed_ns(), Ordering::Relaxed);
}
}
fn enter(&self, _span: &Id) {}
fn exit(&self, _span: &Id) {}
}
#[derive(Default)]
struct LoadVisitor {
matched_quit: bool,
seq: Option<u64>,
subscriptions: Option<u64>,
unkeyed_commands: Option<u64>,
keyed_commands: Option<u64>,
blocked: Option<u64>,
channel: Option<String>,
}
impl LoadVisitor {
fn gauge_sum(&self) -> u64 {
self.subscriptions.unwrap_or(0)
+ self.unkeyed_commands.unwrap_or(0)
+ self.keyed_commands.unwrap_or(0)
+ self.blocked.unwrap_or(0)
}
}
impl Visit for LoadVisitor {
fn record_u64(&mut self, field: &Field, value: u64) {
match field.name() {
"seq" => self.seq = Some(value),
"subscriptions" => self.subscriptions = Some(value),
"unkeyed_commands" => self.unkeyed_commands = Some(value),
"keyed_commands" => self.keyed_commands = Some(value),
"blocked" => self.blocked = Some(value),
_ => {}
}
}
fn record_str(&mut self, field: &Field, value: &str) {
if field.name() == "channel" {
self.channel = Some(value.to_owned());
}
}
fn record_debug(&mut self, field: &Field, value: &dyn Debug) {
if field.name() == "message" {
let text = format!("{value:?}");
if text == "quit signal received" || text == "keyed quit signal received" {
self.matched_quit = true;
}
}
}
}
struct Metrics {
start: Instant,
produced: AtomicU64,
processed: AtomicU64,
producer_done_ns: AtomicU64,
frames: AtomicU64,
rendered_marker: AtomicU64,
update_lat_ns: Mutex<Vec<u64>>,
render_lat_ns: Mutex<Vec<u64>>,
keyed_lat_ns: Mutex<Vec<u64>>,
quit_requested_ns: AtomicU64,
depth_at_quit: AtomicU64,
quit_delivered_ns: AtomicU64,
seq_next: AtomicU64,
seq_broken: AtomicBool,
blocked_at_quit: AtomicU64,
capacity_waits_before_quit: AtomicU64,
blocked_live: AtomicU64,
capacity_wait_shared_ns: Mutex<Vec<u64>>,
}
impl Metrics {
#[expect(
clippy::disallowed_methods,
reason = "calls std Instant::now to stamp the real wall-clock baseline; RFC 0006's acceptance criteria are defined on real time, the sanctioned single-time-source exception (RFC 0009 §3.1)"
)]
fn new() -> Self {
Self {
start: Instant::now(),
produced: AtomicU64::new(0),
processed: AtomicU64::new(0),
producer_done_ns: AtomicU64::new(0),
frames: AtomicU64::new(0),
rendered_marker: AtomicU64::new(0),
update_lat_ns: Mutex::new(Vec::new()),
render_lat_ns: Mutex::new(Vec::new()),
keyed_lat_ns: Mutex::new(Vec::new()),
quit_requested_ns: AtomicU64::new(0),
depth_at_quit: AtomicU64::new(0),
quit_delivered_ns: AtomicU64::new(0),
seq_next: AtomicU64::new(0),
seq_broken: AtomicBool::new(false),
blocked_at_quit: AtomicU64::new(0),
capacity_waits_before_quit: AtomicU64::new(0),
blocked_live: AtomicU64::new(0),
capacity_wait_shared_ns: Mutex::new(Vec::new()),
}
}
fn queue_depth(&self) -> u64 {
let produced = self.produced.load(Ordering::Relaxed);
let processed = self.processed.load(Ordering::Relaxed);
produced.saturating_sub(processed)
}
#[expect(
clippy::disallowed_methods,
reason = "calls std Instant::elapsed to read real wall-clock elapsed time; RFC 0006's acceptance criteria are defined on real time, the sanctioned single-time-source exception (RFC 0009 §3.1)"
)]
fn elapsed_ns(&self) -> u64 {
u64::try_from(self.start.elapsed().as_nanos()).unwrap_or(u64::MAX)
}
#[expect(
clippy::disallowed_methods,
reason = "calls std Instant::elapsed to measure real wall-clock message latency; RFC 0006's acceptance criteria are defined on real time, the sanctioned single-time-source exception (RFC 0009 §3.1)"
)]
fn push_latency(bucket: &Mutex<Vec<u64>>, sent_at: Instant) {
let nanos = u64::try_from(sent_at.elapsed().as_nanos()).unwrap_or(u64::MAX);
bucket.lock().expect("latency bucket poisoned").push(nanos);
}
}
enum Msg {
Load { seq: u64, sent_at: Instant },
KeyedProbe { sent_at: Instant },
}
struct FloodSource {
cfg: ScenarioCfg,
metrics: Arc<Metrics>,
index: u32,
}
impl SubscriptionSource for FloodSource {
type Output = Msg;
type Key = u32;
#[expect(
clippy::disallowed_methods,
reason = "calls std Instant::now to stamp each message's send time and Instant::elapsed to record when the producer finishes, both real wall-clock reads; RFC 0006's acceptance criteria are defined on real time, the sanctioned single-time-source exception (RFC 0009 §3.1)"
)]
fn stream(&self) -> BoxStream<'static, Msg> {
let metrics = Arc::clone(&self.metrics);
let total = self.cfg.total;
let per_tick = if self.cfg.rate == BURST {
usize::try_from(total).expect("total fits in usize")
} else {
usize::try_from((self.cfg.rate / 1_000).max(1)).expect("per-tick fits in usize")
};
let mut ticker = interval(Duration::from_millis(1));
ticker.set_missed_tick_behavior(MissedTickBehavior::Burst);
IntervalStream::new(ticker)
.flat_map(move |_| {
let metrics = Arc::clone(&metrics);
stream::iter((0..per_tick).map(move |_| {
let seq = metrics.produced.fetch_add(1, Ordering::Relaxed);
if seq + 1 == total {
let elapsed =
u64::try_from(metrics.start.elapsed().as_nanos()).unwrap_or(u64::MAX);
metrics.producer_done_ns.store(elapsed, Ordering::Relaxed);
}
Msg::Load {
seq,
sent_at: Instant::now(),
}
}))
})
.take(usize::try_from(total).expect("total fits in usize"))
.chain(stream::pending())
.boxed()
}
fn key(&self) -> Self::Key {
self.index
}
}
struct LoadApp {
cfg: ScenarioCfg,
metrics: Arc<Metrics>,
last_processed: Option<(u64, Instant)>,
processed: u64,
sample_every: u64,
}
impl Application for LoadApp {
type Message = Msg;
type Flags = (ScenarioCfg, Arc<Metrics>);
#[expect(
clippy::disallowed_methods,
reason = "calls std Instant::now to stamp each keyed-probe send time, a real wall-clock read; RFC 0006's acceptance criteria are defined on real time, the sanctioned single-time-source exception (RFC 0009 §3.1)"
)]
fn new((cfg, metrics): Self::Flags) -> (Self, Command<Msg>) {
let cmd = if cfg.keyed_probe {
let mut ticker = interval(Duration::from_millis(25));
ticker.set_missed_tick_behavior(MissedTickBehavior::Skip);
let probes = IntervalStream::new(ticker).map(|_| Msg::KeyedProbe {
sent_at: Instant::now(),
});
Command::stream(probes).cancellable(CommandId::new("keyed-probe"))
} else {
Command::none()
};
let sample_every = (cfg.total / 100_000).max(1);
(
Self {
cfg,
metrics,
last_processed: None,
processed: 0,
sample_every,
},
cmd,
)
}
fn update(&mut self, msg: Msg) -> Command<Msg> {
match msg {
Msg::Load { seq, sent_at } => {
self.processed += 1;
self.metrics
.processed
.store(self.processed, Ordering::Relaxed);
let expected = self.metrics.seq_next.fetch_add(1, Ordering::Relaxed);
if seq != expected {
self.metrics.seq_broken.store(true, Ordering::Relaxed);
}
spin(self.cfg.update_cost);
if seq % self.sample_every == 0 {
Metrics::push_latency(&self.metrics.update_lat_ns, sent_at);
}
self.last_processed = Some((seq, sent_at));
let request_quit = match self.cfg.quit_at_seq {
Some(quit_seq) => seq == quit_seq,
None => self.processed == self.cfg.total,
};
if request_quit {
self.metrics
.depth_at_quit
.store(self.metrics.queue_depth(), Ordering::Relaxed);
self.metrics.blocked_at_quit.store(
self.metrics.blocked_live.load(Ordering::Relaxed),
Ordering::Relaxed,
);
self.metrics
.quit_requested_ns
.store(self.metrics.elapsed_ns(), Ordering::Relaxed);
return if self.cfg.keyed_quit {
Command::quit().cancellable(CommandId::new("quit"))
} else {
Command::quit()
};
}
Command::none()
}
Msg::KeyedProbe { sent_at } => {
Metrics::push_latency(&self.metrics.keyed_lat_ns, sent_at);
Command::none()
}
}
}
fn view(&self, _frame: &mut ratatui::Frame<'_>) {
spin(self.cfg.render_cost);
self.metrics.frames.fetch_add(1, Ordering::Relaxed);
if let Some((seq, sent_at)) = self.last_processed {
let marker = seq + 1;
if self.metrics.rendered_marker.load(Ordering::Relaxed) < marker {
self.metrics
.rendered_marker
.store(marker, Ordering::Relaxed);
Metrics::push_latency(&self.metrics.render_lat_ns, sent_at);
}
}
}
fn subscriptions(&self) -> Vec<Subscription<Msg>> {
(0..self.cfg.producers)
.map(|index| {
Subscription::new(FloodSource {
cfg: self.cfg.clone(),
metrics: Arc::clone(&self.metrics),
index,
})
})
.collect()
}
}
#[expect(
clippy::disallowed_methods,
reason = "calls std Instant::now to busy-wait against a real wall-clock deadline while simulating CPU-bound work; RFC 0006's acceptance criteria are defined on real time, the sanctioned single-time-source exception (RFC 0009 §3.1)"
)]
fn spin(duration: Duration) {
if duration.is_zero() {
return;
}
let deadline = Instant::now() + duration;
while Instant::now() < deadline {
hint::spin_loop();
}
}
struct Report {
cfg: ScenarioCfg,
wall: Duration,
timed_out: bool,
produced: u64,
processed: u64,
frames: u64,
max_depth: u64,
depth_at_producer_done: Option<u64>,
producer_done: Option<Duration>,
update_lat_ns: Vec<u64>,
render_lat_ns: Vec<u64>,
keyed_lat_ns: Vec<u64>,
peak_rss_delta: Option<u64>,
seq_broken: bool,
}
#[expect(
clippy::disallowed_methods,
reason = "calls std Instant::now and Instant::elapsed to measure the scenario's real wall-clock duration; RFC 0006's acceptance criteria are defined on real time, the sanctioned single-time-source exception (RFC 0009 §3.1)"
)]
async fn run_scenario(cfg: ScenarioCfg) -> Report {
let rss_before = peak_rss_bytes();
let metrics = Arc::new(Metrics::new());
let stop = Arc::new(AtomicBool::new(false));
let sampler = {
let metrics = Arc::clone(&metrics);
let stop = Arc::clone(&stop);
tokio::spawn(async move {
let mut samples: Vec<(Duration, u64)> = Vec::new();
let mut ticker = interval(Duration::from_millis(5));
while !stop.load(Ordering::Relaxed) {
ticker.tick().await;
samples.push((metrics.start.elapsed(), metrics.queue_depth()));
}
samples
})
};
let runtime = cfg.mode.build_runtime((cfg.clone(), Arc::clone(&metrics)));
let mut terminal =
Terminal::new(TestBackend::new(120, 40)).expect("test backend terminal creation");
let started = Instant::now();
let timed_out = timeout(cfg.max_wall, runtime.run(&mut terminal))
.await
.is_err();
let wall = started.elapsed();
await_quiescence().await;
stop.store(true, Ordering::Relaxed);
let samples = sampler.await.expect("sampler task");
let producer_done_ns = metrics.producer_done_ns.load(Ordering::Relaxed);
let producer_done = (producer_done_ns > 0).then(|| Duration::from_nanos(producer_done_ns));
let depth_at_producer_done = producer_done.and_then(|done| {
samples
.iter()
.find(|(at, _)| *at >= done)
.map(|(_, depth)| *depth)
});
let take_sorted = |bucket: &Mutex<Vec<u64>>| {
let mut values = bucket.lock().expect("latency bucket poisoned").clone();
values.sort_unstable();
values
};
Report {
wall,
timed_out,
produced: metrics.produced.load(Ordering::Relaxed),
processed: metrics.processed.load(Ordering::Relaxed),
frames: metrics.frames.load(Ordering::Relaxed),
max_depth: samples.iter().map(|(_, depth)| *depth).max().unwrap_or(0),
depth_at_producer_done,
producer_done,
update_lat_ns: take_sorted(&metrics.update_lat_ns),
render_lat_ns: take_sorted(&metrics.render_lat_ns),
keyed_lat_ns: take_sorted(&metrics.keyed_lat_ns),
peak_rss_delta: match (rss_before, peak_rss_bytes()) {
(Some(before), Some(after)) => Some(after.saturating_sub(before)),
_ => None,
},
seq_broken: metrics.seq_broken.load(Ordering::Relaxed),
cfg,
}
}
struct QuitTrialSample {
depth: u64,
to_delivered_ns: u64,
to_exit_ns: u64,
}
enum QuitTrialFailure {
TimedOut,
NoDeliveryEvent,
PredicateMiss,
}
struct QuitReport {
cfg: ScenarioCfg,
trials: u32,
attempts: u32,
timeouts: u32,
missing_delivery: u32,
predicate_misses: u32,
cap_exhausted: bool,
depths: Vec<u64>,
to_delivered_ns: Vec<u64>,
to_exit_ns: Vec<u64>,
}
impl QuitReport {
const fn failed(&self) -> bool {
self.timeouts > 0
|| self.missing_delivery > 0
|| self.cap_exhausted
|| (self.depths.len() as u32) < self.trials
}
}
async fn run_quit_trial(
cfg: ScenarioCfg,
valid_trial: ValidTrial,
) -> Result<QuitTrialSample, QuitTrialFailure> {
let metrics = Arc::new(Metrics::new());
let runtime = cfg.mode.build_runtime((cfg.clone(), Arc::clone(&metrics)));
let mut terminal =
Terminal::new(TestBackend::new(120, 40)).expect("test backend terminal creation");
*TRIAL_METRICS.lock().expect("trial metrics slot poisoned") = Some(Arc::clone(&metrics));
let timed_out = timeout(cfg.max_wall, runtime.run(&mut terminal))
.await
.is_err();
let exit_ns = metrics.elapsed_ns();
*TRIAL_METRICS.lock().expect("trial metrics slot poisoned") = None;
await_quiescence().await;
if timed_out {
return Err(QuitTrialFailure::TimedOut);
}
let quit_ns = metrics.quit_requested_ns.load(Ordering::Relaxed);
let delivered_ns = metrics.quit_delivered_ns.load(Ordering::Relaxed);
if quit_ns == 0 || delivered_ns == 0 {
return Err(QuitTrialFailure::NoDeliveryEvent);
}
let window_start = quit_ns.saturating_sub(5_000_000);
let churn = metrics
.capacity_wait_shared_ns
.lock()
.expect("capacity-wait log poisoned")
.iter()
.filter(|&&at| at >= window_start && at <= quit_ns)
.count();
metrics
.capacity_waits_before_quit
.store(u64::try_from(churn).unwrap_or(u64::MAX), Ordering::Relaxed);
if !valid_trial.holds(&metrics) {
return Err(QuitTrialFailure::PredicateMiss);
}
Ok(QuitTrialSample {
depth: metrics.depth_at_quit.load(Ordering::Relaxed),
to_delivered_ns: delivered_ns.saturating_sub(quit_ns),
to_exit_ns: exit_ns.saturating_sub(quit_ns),
})
}
async fn run_quit_scenario(scenario: &QuitScenarioCfg) -> QuitReport {
let attempt_cap = match scenario.valid_trial {
ValidTrial::Always => u32::MAX,
_ => scenario.trials.saturating_mul(10),
};
let mut attempts = 0u32;
let mut timeouts = 0;
let mut missing_delivery = 0;
let mut predicate_misses = 0;
let mut cap_exhausted = false;
let mut depths = Vec::new();
let mut to_delivered_ns = Vec::new();
let mut to_exit_ns = Vec::new();
while (depths.len() as u32) < scenario.trials {
if attempts >= attempt_cap {
cap_exhausted = true;
break;
}
attempts += 1;
match run_quit_trial(scenario.base.clone(), scenario.valid_trial).await {
Ok(sample) => {
depths.push(sample.depth);
to_delivered_ns.push(sample.to_delivered_ns);
to_exit_ns.push(sample.to_exit_ns);
}
Err(QuitTrialFailure::PredicateMiss) => predicate_misses += 1,
Err(QuitTrialFailure::TimedOut) => {
timeouts += 1;
break;
}
Err(QuitTrialFailure::NoDeliveryEvent) => {
missing_delivery += 1;
break;
}
}
}
depths.sort_unstable();
to_delivered_ns.sort_unstable();
to_exit_ns.sort_unstable();
QuitReport {
cfg: scenario.base.clone(),
trials: scenario.trials,
attempts,
timeouts,
missing_delivery,
predicate_misses,
cap_exhausted,
depths,
to_delivered_ns,
to_exit_ns,
}
}
fn print_quit_report(report: &QuitReport) {
let cfg = &report.cfg;
println!("## {}", cfg.name);
let rate = if cfg.rate == BURST {
"burst".to_owned()
} else {
format!("{}/s", cfg.rate)
};
println!(
" load: rate={rate} total={} update_cost={:?} quit_at_seq={} keyed_quit={}",
cfg.total,
cfg.update_cost,
cfg.quit_at_seq.expect("quit scenarios set quit_at_seq"),
cfg.keyed_quit,
);
println!(
" trials: {} valid / {} required ({} attempts, {} predicate misses, \
{} timed out, {} missing delivery){}",
report.depths.len(),
report.trials,
report.attempts,
report.predicate_misses,
report.timeouts,
report.missing_delivery,
if report.cap_exhausted {
", ATTEMPT-CAP EXHAUSTED"
} else {
""
},
);
if report.depths.is_empty() {
return;
}
println!(
" depth at quit: min={} p50={} max={}",
report.depths.first().expect("non-empty"),
percentile(&report.depths, 0.50),
report.depths.last().expect("non-empty"),
);
println!(
" quit -> delivered: {}",
format_lat(&report.to_delivered_ns)
);
println!(" quit -> exit: {}", format_lat(&report.to_exit_ns));
println!();
}
fn percentile(sorted: &[u64], p: f64) -> u64 {
if sorted.is_empty() {
return 0;
}
let rank = ((sorted.len() as f64) * p).ceil() as usize;
sorted[rank.clamp(1, sorted.len()) - 1]
}
fn format_lat(sorted: &[u64]) -> String {
if sorted.is_empty() {
return "n/a".to_owned();
}
let ms = |ns: u64| ns as f64 / 1_000_000.0;
format!(
"p50={:.3}ms p95={:.3}ms p99={:.3}ms max={:.3}ms (n={})",
ms(percentile(sorted, 0.50)),
ms(percentile(sorted, 0.95)),
ms(percentile(sorted, 0.99)),
ms(*sorted.last().expect("non-empty")),
sorted.len(),
)
}
fn print_report(report: &Report) {
let cfg = &report.cfg;
println!("## {}", cfg.name);
let rate = if cfg.rate == BURST {
"burst".to_owned()
} else {
format!("{}/s", cfg.rate)
};
println!(
" load: rate={rate} total={} update_cost={:?} render_cost={:?} keyed_probe={}",
cfg.total, cfg.update_cost, cfg.render_cost, cfg.keyed_probe
);
let status = if report.timed_out { "TIMED OUT" } else { "ok" };
println!(
" run: {status} wall={:.2}s produced={} processed={} throughput={:.0}/s",
report.wall.as_secs_f64(),
report.produced,
report.processed,
report.processed as f64 / report.wall.as_secs_f64(),
);
println!(
" frames: {} ({:.1} fps effective)",
report.frames,
report.frames as f64 / report.wall.as_secs_f64(),
);
let backlog_bytes = report.max_depth * mem::size_of::<Msg>() as u64;
println!(
" queue: max_depth={} (~{:.1} MiB backlog)",
report.max_depth,
backlog_bytes as f64 / (1024.0 * 1024.0),
);
if let (Some(done), Some(depth)) = (report.producer_done, report.depth_at_producer_done) {
let drain = report.wall.saturating_sub(done);
println!(
" producer done at {:.2}s: depth={depth} drain={:.2}s",
done.as_secs_f64(),
drain.as_secs_f64(),
);
}
println!(" update latency: {}", format_lat(&report.update_lat_ns));
println!(" render latency: {}", format_lat(&report.render_lat_ns));
if cfg.keyed_probe {
println!(" keyed latency: {}", format_lat(&report.keyed_lat_ns));
}
if let Some(delta) = report.peak_rss_delta {
println!(
" peak RSS delta: {:.1} MiB (process-wide, monotone across scenarios)",
delta as f64 / (1024.0 * 1024.0),
);
}
println!();
}
#[cfg(unix)]
fn peak_rss_bytes() -> Option<u64> {
let mut usage = mem::MaybeUninit::<libc::rusage>::zeroed();
let rc = unsafe { libc::getrusage(libc::RUSAGE_SELF, usage.as_mut_ptr()) };
if rc != 0 {
return None;
}
let usage = unsafe { usage.assume_init() };
let raw = u64::try_from(usage.ru_maxrss).ok()?;
if cfg!(target_os = "macos") {
Some(raw)
} else {
Some(raw * 1024)
}
}
#[cfg(not(unix))]
fn peak_rss_bytes() -> Option<u64> {
None
}
fn scenario_named(name: &str) -> ScenarioCfg {
scenarios()
.into_iter()
.find(|cfg| cfg.name == name)
.expect("scenario name present in the canonical table")
}
fn quit_scenario_named(name: &str) -> QuitScenarioCfg {
quit_scenarios()
.into_iter()
.find(|cfg| cfg.base.name == name)
.expect("quit scenario name present in the canonical table")
}
fn smoke_load_scenarios() -> Vec<ScenarioCfg> {
vec![
ScenarioCfg {
total: 10_000,
..scenario_named("steady_20k")
},
ScenarioCfg {
name: "burst_20k_bounded",
total: 20_000,
..scenario_named("burst_200k_bounded")
},
]
}
fn smoke_quit_scenarios() -> Vec<QuitScenarioCfg> {
vec![
QuitScenarioCfg {
trials: 5,
..quit_scenario_named("quit_idle_bounded")
},
QuitScenarioCfg {
trials: 5,
..quit_scenario_named("quit_blocked_1")
},
]
}
fn run_smoke(runtime: &TokioRuntime) -> bool {
println!("# tears runtime load harness — smoke profile\n");
let mut ok = true;
for cfg in smoke_load_scenarios() {
let report = runtime.block_on(run_scenario(cfg));
print_report(&report);
if report.timed_out {
eprintln!("smoke: draining scenario `{}` timed out", report.cfg.name);
ok = false;
}
if report.seq_broken || report.processed != report.cfg.total {
eprintln!(
"smoke: draining scenario `{}` did not deliver the exact sequence \
0..{} (processed={}, seq_broken={})",
report.cfg.name, report.cfg.total, report.processed, report.seq_broken,
);
ok = false;
}
}
for scenario in smoke_quit_scenarios() {
let report = runtime.block_on(run_quit_scenario(&scenario));
print_quit_report(&report);
if report.failed() {
eprintln!("smoke: quit scenario `{}` failed", report.cfg.name);
ok = false;
}
}
ok
}
const ISO_SATURATED_KEYS: usize = 8;
const ISO_KEYS: usize = ISO_SATURATED_KEYS + 1;
struct IsoMetrics {
key_yields: Vec<Arc<AtomicU64>>,
keyed_delivered: AtomicU64,
shared_produced: AtomicU64,
shared_processed: AtomicU64,
max_shared_depth: AtomicU64,
concurrent_shared_depth: AtomicU64,
}
impl IsoMetrics {
fn new() -> Self {
Self {
key_yields: (0..ISO_KEYS).map(|_| Arc::new(AtomicU64::new(0))).collect(),
keyed_delivered: AtomicU64::new(0),
shared_produced: AtomicU64::new(0),
shared_processed: AtomicU64::new(0),
max_shared_depth: AtomicU64::new(0),
concurrent_shared_depth: AtomicU64::new(0),
}
}
fn shared_depth(&self) -> u64 {
self.shared_produced
.load(Ordering::Relaxed)
.saturating_sub(self.shared_processed.load(Ordering::Relaxed))
}
fn saturated(&self, key: usize, keyed_cap: u64) -> bool {
self.key_yields[key].load(Ordering::Relaxed) > keyed_cap
}
}
#[derive(Clone)]
enum IsoMsg {
Flood(u64),
KeyedOut,
}
struct IsoFloodSource {
iso: Arc<IsoMetrics>,
}
impl SubscriptionSource for IsoFloodSource {
type Output = IsoMsg;
type Key = u32;
fn stream(&self) -> BoxStream<'static, IsoMsg> {
let iso = Arc::clone(&self.iso);
stream::repeat(())
.map(move |()| IsoMsg::Flood(iso.shared_produced.fetch_add(1, Ordering::Relaxed)))
.boxed()
}
fn key(&self) -> Self::Key {
0
}
}
fn iso_keyed_stream(
counter: Arc<AtomicU64>,
) -> impl futures::Stream<Item = IsoMsg> + Send + 'static {
stream::repeat(()).map(move |()| {
counter.fetch_add(1, Ordering::Relaxed);
IsoMsg::KeyedOut
})
}
struct KeyedIsolationApp {
iso: Arc<IsoMetrics>,
keyed_cap: u64,
app_cap: u64,
saturators_started: usize,
probe_started: bool,
}
impl KeyedIsolationApp {
fn spawn_key(&self, key: usize) -> Command<IsoMsg> {
let counter = Arc::clone(&self.iso.key_yields[key]);
Command::stream(iso_keyed_stream(counter)).cancellable(CommandId::new(key as u64))
}
}
impl Application for KeyedIsolationApp {
type Message = IsoMsg;
type Flags = (Arc<IsoMetrics>, u64, u64);
fn new((iso, keyed_cap, app_cap): Self::Flags) -> (Self, Command<IsoMsg>) {
(
Self {
iso,
keyed_cap,
app_cap,
saturators_started: 0,
probe_started: false,
},
Command::none(),
)
}
fn update(&mut self, msg: IsoMsg) -> Command<IsoMsg> {
let seq = match msg {
IsoMsg::KeyedOut => {
self.iso.keyed_delivered.fetch_add(1, Ordering::Relaxed);
return Command::none();
}
IsoMsg::Flood(seq) => seq,
};
let _ = seq;
spin(Duration::from_micros(10));
self.iso.shared_processed.fetch_add(1, Ordering::Relaxed);
self.iso
.max_shared_depth
.fetch_max(self.iso.shared_depth(), Ordering::Relaxed);
if self.saturators_started < ISO_SATURATED_KEYS {
let key = self.saturators_started;
self.saturators_started += 1;
return self.spawn_key(key);
}
let saturators_saturated =
(0..ISO_SATURATED_KEYS).all(|k| self.iso.saturated(k, self.keyed_cap));
if !self.probe_started {
if saturators_saturated {
self.probe_started = true;
return self.spawn_key(ISO_SATURATED_KEYS);
}
return Command::none();
}
let all_saturated = (0..ISO_KEYS).all(|k| self.iso.saturated(k, self.keyed_cap));
if all_saturated {
self.iso
.concurrent_shared_depth
.fetch_max(self.iso.shared_depth(), Ordering::Relaxed);
if self.iso.concurrent_shared_depth.load(Ordering::Relaxed) > self.app_cap {
return Command::quit();
}
}
Command::none()
}
fn view(&self, _frame: &mut ratatui::Frame<'_>) {}
fn subscriptions(&self) -> Vec<Subscription<IsoMsg>> {
vec![Subscription::new(IsoFloodSource {
iso: Arc::clone(&self.iso),
})]
}
}
struct IsoReport {
keyed_cap: u64,
app_cap: u64,
timed_out: bool,
yields: Vec<u64>,
keyed_delivered: u64,
max_shared_depth: u64,
concurrent_shared_depth: u64,
}
impl IsoReport {
fn isolated(&self) -> bool {
!self.timed_out
&& self.keyed_delivered == 0
&& self.yields.iter().all(|&y| y == self.keyed_cap + 1)
&& self.concurrent_shared_depth == self.app_cap + 1
}
}
async fn run_keyed_isolation() -> IsoReport {
let keyed_cap = KEYED_CHANNEL_CAPACITY as u64;
let app_cap = APP_CHANNEL_CAPACITY as u64;
let iso = Arc::new(IsoMetrics::new());
let runtime = Runtime::<KeyedIsolationApp>::with_config(
(Arc::clone(&iso), keyed_cap, app_cap),
bounded_config(),
);
let mut terminal =
Terminal::new(TestBackend::new(120, 40)).expect("test backend terminal creation");
let timed_out = timeout(Duration::from_secs(10), runtime.run(&mut terminal))
.await
.is_err();
await_quiescence().await;
let yields = iso
.key_yields
.iter()
.map(|counter| counter.load(Ordering::Relaxed))
.collect();
IsoReport {
keyed_cap,
app_cap,
timed_out,
yields,
keyed_delivered: iso.keyed_delivered.load(Ordering::Relaxed),
max_shared_depth: iso.max_shared_depth.load(Ordering::Relaxed),
concurrent_shared_depth: iso.concurrent_shared_depth.load(Ordering::Relaxed),
}
}
fn print_iso_report(report: &IsoReport) {
println!("## keyed_isolation");
println!(
" {} keyed channels ({} saturated + 1 probe), capacity {}",
report.yields.len(),
ISO_SATURATED_KEYS,
report.keyed_cap,
);
println!(
" status: {}",
if report.timed_out {
"TIMED OUT — full saturation never coincided with a full shared channel \
(possible shared pool)"
} else {
"ok"
},
);
println!(
" per-key raw yields: {:?} (each must equal capacity + 1 = {})",
report.yields,
report.keyed_cap + 1,
);
println!(
" keyed delivered to update: {} (must be 0)",
report.keyed_delivered,
);
println!(
" concurrent shared depth: {} (must equal app_channel_capacity + 1 = {}; \
whole-run max {})",
report.concurrent_shared_depth,
report.app_cap + 1,
report.max_shared_depth,
);
println!(" isolation: {}", report.isolated());
println!();
}
fn main() -> ExitCode {
let args: Vec<String> = env::args().skip(1).collect();
let smoke = args.iter().any(|arg| arg == "--smoke");
let selected: Vec<String> = args
.into_iter()
.filter(|arg| !arg.starts_with('-'))
.collect();
set_global_default(QuitDeliverySubscriber)
.expect("no other global tracing subscriber is installed");
let runtime = Builder::new_multi_thread()
.enable_all()
.build()
.expect("tokio runtime");
if smoke {
return if run_smoke(&runtime) {
ExitCode::SUCCESS
} else {
eprintln!("error: smoke profile failed");
ExitCode::FAILURE
};
}
let matches = |name: &str| selected.is_empty() || selected.iter().any(|s| s == name);
let load_to_run: Vec<ScenarioCfg> = scenarios()
.into_iter()
.filter(|cfg| matches(cfg.name))
.collect();
let quit_to_run: Vec<QuitScenarioCfg> = quit_scenarios()
.into_iter()
.filter(|scenario| matches(scenario.base.name))
.collect();
let run_iso = matches("keyed_isolation");
if load_to_run.is_empty() && quit_to_run.is_empty() && !run_iso {
let names: Vec<&str> = scenarios()
.into_iter()
.map(|cfg| cfg.name)
.chain(
quit_scenarios()
.into_iter()
.map(|scenario| scenario.base.name),
)
.chain(iter::once("keyed_isolation"))
.collect();
println!("no matching scenario; available: {}", names.join(", "));
return ExitCode::FAILURE;
}
println!("# tears runtime load harness\n");
for cfg in load_to_run {
let report = runtime.block_on(run_scenario(cfg));
print_report(&report);
}
let mut any_failed = false;
for scenario in quit_to_run {
let report = runtime.block_on(run_quit_scenario(&scenario));
let failed = report.failed();
print_quit_report(&report);
any_failed |= failed;
}
if run_iso {
let report = runtime.block_on(run_keyed_isolation());
let failed = !report.isolated();
print_iso_report(&report);
any_failed |= failed;
}
if any_failed {
eprintln!("error: one or more scenarios failed");
return ExitCode::FAILURE;
}
ExitCode::SUCCESS
}