Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tutorial 35: Performance measurement and resilient operation

Performance is a property of a concrete application, build, host and workload. Rullst includes Criterion microbenchmarks and production helpers, but does not promise a universal latency, throughput or availability number.

1. Build an application-specific release binary

[profile.release]
opt-level = 3
lto = "thin"
codegen-units = 1
strip = "debuginfo"

Alternative linkers such as mold or lld can improve developer link time on supported hosts. target-cpu=native can improve a host-specific binary but makes it less portable; do not put it in a generally distributed artifact without an explicit CPU baseline.

2. Configure and measure the database pool

#![allow(unused)]
fn main() {
use rullst_orm::Orm;

async fn configure() -> Result<(), rullst_orm::Error> {
Orm::init_with_options(
    "postgres://app:password@127.0.0.1/app",
    20, // maximum connections
    10, // acquire timeout in seconds
)
.await?;
Ok(())
}
}

Choose limits from database capacity and measured concurrency. More connections can increase contention and resource use instead of increasing throughput.

3. Run reproducible benchmarks

cargo bench --workspace

Record at least:

  • exact commit, Rust version, features and release profile;
  • CPU, memory, operating system and power/virtualization settings;
  • database/provider version and topology;
  • warm-up, sample count, concurrency and payload distribution;
  • median and tail latency, throughput, errors and resource use.

Criterion microbenchmarks detect regressions in selected functions. They do not model a production network, database, proxy or user journey. The separate cross-framework repository currently exercises historical Rullst 4.x and is not v12 evidence until refreshed.

The public benchmark hub links the eight published groups: facade/HTTP, Core primitives, ORM, Auth, Connect, Security, AI and Capital. Nine Criterion binaries back those groups because ORM has both local and cross-ORM inputs. A crate without a microbenchmark is not automatically less mature: protocol vectors, generated-project compilation, restart/failure contracts, no_std target builds or whole-request tests can fit its dominant risk better. Add a new benchmark only with a stable operation, input, unit and interpretation.

The repository now also contains a v12 cross-ORM SQLite harness:

cargo bench -p rullst-orm --features strict-sqlite \
  --bench orm_comparison

It pins Diesel and SeaORM in the lockfile and gives all three ORMs one typed SQLite connection, separate database files, the same schema/unique index, 100 equivalent rows and identical WAL/synchronous/busy-timeout policy. Criterion measures primary-key lookup, indexed filtered lookup, count, ordered list-ten and insert/delete. This makes the input inspectable; it does not make the architectures identical. Diesel’s synchronous call path and the async Rullst/SeaORM executor paths remain part of what is measured.

The first local smoke run contradicted the old “negligible overhead versus Diesel” wording: Diesel led these five SQLite shapes. Rullst was competitive with SeaORM on reads but did not lead every operation. Keep the per-commit CI history as regression/comparison evidence and never generalize it to networked PostgreSQL/MySQL, concurrency, memory use or complete applications.

4. Test failure behavior separately

Availability requires deployment exercises: health/readiness semantics, timeouts, overload, cancellation, database failover, backup/restore, migration rollback and secret rotation. Miri, sanitizers, fuzzing and Kani are target-specific correctness tools; none measures availability or proves the absence of every memory error.