#Performance Tuning Guide

Version: 0.33.0 Updated: 2026-03-15 Applies to: ranvier-core, ranvier-runtime Category: Operations


#1. Release Profile

Ranvier ships with an optimized release profile in the workspace Cargo.toml:

[profile.release]
lto = true        # Link-Time Optimization (cross-crate inlining)
strip = true      # Strip debug symbols from binary
codegen-units = 1 # Single codegen unit for maximum optimization
opt-level = 3     # Maximum optimization level

Build with: cargo build --release

Expected impact:

  • Binary size: ~30-50% smaller
  • Runtime latency: ~5-15% faster (LTO enables cross-crate inlining)
  • Build time: ~2-3x slower (trade-off for runtime performance)

#2. Bus Resource Access Patterns

The Bus uses AHashMap<TypeId, Box<dyn Any>> for O(1) type-indexed resource lookups.

#Best Practices

Cache references instead of repeated lookups:

// โŒ Bad โ€” multiple lookups
async fn handle(&self, input: Input, _: &Res, bus: &mut Bus) -> Outcome<Output, Error> {
    let db = bus.read::<DbPool>().unwrap();
    do_query(db).await;
    let db = bus.read::<DbPool>().unwrap(); // redundant lookup
    do_another_query(db).await;
    // ...
}

// โœ… Good โ€” single lookup, reuse reference
async fn handle(&self, input: Input, _: &Res, bus: &mut Bus) -> Outcome<Output, Error> {
    let db = bus.read::<DbPool>().unwrap();
    do_query(db).await;
    do_another_query(db).await;
    // ...
}

Use Res (resource tuple) for compile-time access when possible:

// Resources passed via Res tuple have zero overhead โ€” no HashMap lookup
impl Transition<Input, Output, Error, (DbPool, Config)> for MyStep {
    async fn handle(&self, input: Input, (db, config): &(DbPool, Config), bus: &mut Bus) -> Outcome<Output, Error> {
        // db and config accessed directly โ€” no Bus lookup needed
    }
}

#3. Axon Circuit Optimization

#Keep hot paths short

// โœ… Good โ€” common case has minimal steps
let axon = Axon::new("fast-path")
    .then(Validate)      // fast check
    .then(Process)       // main logic
    .then(Respond);      // serialize

// โŒ Avoid โ€” unnecessary steps in hot path
let axon = Axon::new("slow-path")
    .then(LogEntry)      // move to middleware
    .then(Validate)
    .then(AuditTrail)    // move to async post-processing
    .then(Process)
    .then(LogExit)       // move to middleware
    .then(Respond);

#Use middleware layers for cross-cutting concerns

Move logging, metrics, and audit to Tower layers rather than Axon steps.


#4. Compilation Time Tips

# Use cargo check (no codegen) for rapid feedback
cargo check --workspace

# Use sccache for shared compilation cache
cargo install sccache
export RUSTC_WRAPPER=sccache

# Limit parallel compilation to reduce memory pressure
export CARGO_BUILD_JOBS=4

# Use incremental compilation (default in debug)
export CARGO_INCREMENTAL=1

#5. Dependency Feature Audit

Regularly audit dependency features to minimize compilation scope:

# Find unused dependencies
cargo install cargo-udeps
cargo +nightly udeps

# Analyze binary size by function
cargo install cargo-bloat
cargo bloat --release --crates

#6. References