tursodatabase/turso · warning
no CPU samples collected; increase --queries or --seconds
Error message
no CPU samples collected; increase --queries or --seconds
What it means
After stopping the CPU profiler, finish() builds a report and requires at least one collected sample before producing a flamegraph. ensure! in perf/fts/src/profiling.rs:31 fails when report.data is empty, meaning the profiled workload was too short or too light for the sampler to record any frames.
Solutions
- Increase --queries (search mode) or --seconds (throughput mode) so the run lasts long enough to sample
- Lower the profiler sampling interval if the profiler configuration allows it
- Skip profiling for tiny runs: only enable the profiler for realistically sized workloads
- Confirm the profiler was actually enabled/attached (an enabled profiler with no path or no samples may indicate attachment failure)
Example fix
// before fts-bench --benchmark search --queries 1 --profile out.svg // after fts-bench --benchmark search --queries 100000 --profile out.svg
Defensive patterns
Strategy: validation
Validate before calling
if queries < 10_000 && seconds.unwrap_or(5.0) < 1.0 { eprintln!("workload too small for CPU profiling; increase --queries or --seconds"); } Prevention
- Only enable profiling for workloads running at least a few seconds
- Scale --queries/--seconds up whenever --profile is passed
- Check profiler attachment (output path present) before interpreting empty reports
- Lower sampling interval for short runs if the profiler supports it
When it happens
Trigger: Calling finish() on an enabled profiler whose capture window contained no samples — typically a benchmark run with very few queries (--queries 1) or a sub-second --seconds window, so the sampling interval never fired.
Common situations: Profiling a quick smoke test instead of a real run; high sampling interval combined with tiny workloads; records_worker_cpu_without_rendering_svg-style tests driving a profiler with minimal work; profiler attached but workload finishing before the first tick.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- BEGIN must start a transaction
- COMMIT must end the transaction
- COMMIT must end the transaction
- connections must be positive
- connections must be positive
AI-assisted analysis of tursodatabase/turso@8d4a589f8d (2026-09-20).
Data as JSON: /api/errors/aafcc44acd2b8bf0.
Report an issue: GitHub.
Appendix: source
Thrown at perf/fts/src/profiling.rs:31
#[cfg(any(
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "riscv64",
target_arch = "loongarch64"
))]
let builder = builder.blocklist(&["libc", "libgcc", "pthread", "vdso"]);
Ok(Some(builder.build()?))
}
pub fn finish(profiler: Option<pprof::ProfilerGuard<'static>>, path: Option<&Path>) -> Result<()> {
let Some(profiler) = profiler else {
assert!(path.is_none());
return Ok(());
};
let report = profiler.report().build()?;
drop(profiler);
let path = path.expect("enabled profiler must have an output path");
ensure!(
!report.data.is_empty(),
"no CPU samples collected; increase --queries or --seconds"
);
let mut stacks = BTreeMap::<String, isize>::new();
for (frames, count) in &report.data {
let mut names = vec![frames.thread_name_or_id()];
for frame in frames.frames.iter().rev() {
for symbol in frame.iter().rev() {
names.push(symbol.name().replace(';', ":"));
}
}
*stacks.entry(names.join(";")).or_default() += count;
}
let mut folded = BufWriter::new(File::create_new(path.with_extension("folded"))?);
for (stack, count) in stacks {
writeln!(folded, "{stack} {count}")?;
}
folded.flush()?;View on GitHub (pinned to 8d4a589f8d)