Value-of-Information Sampling
What goes wrong with a naive approach
A lot of runtime decisions depend on measurements that are themselves expensive — a detailed frame snapshot, a full buffer diff, a conformal calibration pass. The naive approach is a timer: sample every milliseconds regardless of whether anything is happening.
The problem is that a timer has no idea whether sampling would change any decision. If the posterior over “is this frame a violation?” is already sharp at , sampling makes it sharper at — not actionable, not useful, just overhead. If the posterior is and any new observation would flip the decision, sampling is absolutely worth the cost.
The right quantity is the value of information (VOI): the expected reduction in posterior variance from taking one more sample. Sample iff the VOI gain justifies the cost.
Mental model
Maintain a Beta posterior over the quantity of interest (typically “probability this measurement violates the SLO”). Compare the current posterior variance to the expected posterior variance after one more observation.
- Current variance .
- Expected post-sample variance — averaging over what the next observation might be.
VOI is the difference. Sample iff:
(i.e., the information gain, valued appropriately, exceeds the cost
of the measurement) OR the max_interval timer has expired. The
timer provides a safety net — VOI alone can starve a stale posterior.
VOI sampling is the principled cousin of adaptive sampling. It doesn’t need a learning-rate schedule, a backoff policy, or a probe frequency knob. The sample-iff inequality decides.
The math
Beta posterior summaries
Post-sample variance (one observation)
If we observed a success, :
If we observed a failure, :
Expected post-sample variance
VOI and the sample-iff rule
Sample iff:
Defaults (TUI-calibrated)
| Parameter | Default |
|---|---|
| (prior successes) | 1 |
| (prior failures) | 9 |
| (boundary) | 0.05 |
| (e-process betting) | 0.5 |
sample_cost | 0.08 |
min_interval_ms | 100 |
max_interval_ms | 1000 |
The prior encodes “SLO violations are rare” — a reasonable prior for most TUI metrics. The 100–1000 ms clamps the sampling rate to between 1 Hz and 10 Hz.
Worked example — rare-event posterior
Prior (mean 0.1). After 50 successes, 2 failures the posterior is :
Expected post-sample variance is about . VOI . With and :
VOI says no. But if the timer has been ticking for 1000 ms with no
sample, the max_interval clause fires — keeping the posterior
from going stale.
When the stream shifts and the posterior pulls toward 0.4 with high variance, VOI grows rapidly and sampling becomes economic again.
Rust interface
use ftui_runtime::voi_sampling::{VoiSampler, VoiConfig, SampleDecision};
let mut sampler = VoiSampler::new(VoiConfig {
prior_alpha: 1.0,
prior_beta: 9.0,
mu_0: 0.05,
lambda: 0.5,
sample_cost: 0.08,
min_interval_ms: 100,
max_interval_ms: 1000,
});
// Once per frame:
match sampler.decide(now) {
SampleDecision::Sample { reason } => {
let x = take_measurement();
sampler.observe(x);
}
SampleDecision::Skip { reason: _ } => {}
}VoiSampler also exposes the e-value for pairing with an
anytime-valid alert layer; see e-processes.
How to debug
Every decision emits a voi_decision line:
{"schema":"voi_decision","should_sample":false,
"voi_gain":1.1e-5,"score":0.0011,"cost":0.08,
"e_value":0.94,"boundary_score":0.55,
"reason":"voi_below_cost","interval_ms":220}FTUI_EVIDENCE_SINK=/tmp/ftui.jsonl cargo run -p ftui-demo-showcase
# Histogram of sampling reasons:
jq -c 'select(.schema=="voi_decision") | .reason' \
/tmp/ftui.jsonl | sort | uniq -cmax_interval firing constantly means VOI is saying no every time —
either your is too small or your posterior is
already sharp and you’re wasting measurements.
Pitfalls
sample_cost is expressed in the same units as VOI gain. VOI
is in variance units (roughly squared probability); sample_cost
is a tuning constant that matches. If you change the prior or the
observation model, recalibrate sample_cost empirically.
The Beta model assumes Bernoulli observations. If your stream is continuous (e.g., frame-time microseconds), wrap it in a threshold test first — “is ?” — and feed the Bernoulli outcome to the sampler. Using a Gaussian stream directly misreports VOI.
Cross-references
- Hint ranking — a different consumer of the same Beta-posterior machinery.
/runtime/overview— where the sampler is wired into the frame loop.- E-processes — the anytime-valid alert layer that pairs with VOI sampling.