Crate mobench_sdk

Crate mobench_sdk 

Source
Expand description

§mobench-sdk

A mobile benchmarking SDK for Rust that enables running performance benchmarks on real Android and iOS devices via BrowserStack App Automate.

§Overview

mobench-sdk provides a simple, declarative API for defining benchmarks that can run on mobile devices. It handles the complexity of cross-compilation, FFI bindings, and mobile app packaging automatically.

§Quick Start

§1. Add Dependencies

[dependencies]
mobench-sdk = "0.1"
inventory = "0.3"  # Required for benchmark registration

§2. Define Benchmarks

Use the #[benchmark] attribute to mark functions for benchmarking:

use mobench_sdk::benchmark;

#[benchmark]
fn my_expensive_operation() {
    let result = expensive_computation();
    std::hint::black_box(result);  // Prevent optimization
}

#[benchmark]
fn another_benchmark() {
    for i in 0..1000 {
        std::hint::black_box(i * i);
    }
}

§3. Build and Run

Use the mobench CLI to build and run benchmarks:

# Install the CLI
cargo install mobench

# Build for Android (outputs to target/mobench/)
cargo mobench build --target android

# Build for iOS
cargo mobench build --target ios

# Run on BrowserStack
cargo mobench run --target android --function my_expensive_operation \
    --iterations 100 --warmup 10 --devices "Google Pixel 7-13.0"

§Architecture

The SDK consists of several components:

ModuleDescription
registryRuntime discovery of #[benchmark] functions
runnerBenchmark execution and timing infrastructure
buildersAndroid and iOS build automation
codegenMobile app template generation
typesCommon types and error definitions

§Crate Ecosystem

The mobench ecosystem consists of four crates:

  • mobench-sdk (this crate) - Core SDK library with build automation
  • mobench - CLI tool for building and running benchmarks
  • mobench-macros - #[benchmark] proc macro
  • mobench-runner - Lightweight timing harness

§Programmatic Usage

You can also use the SDK programmatically:

§Using the Builder Pattern

use mobench_sdk::BenchmarkBuilder;

let report = BenchmarkBuilder::new("my_benchmark")
    .iterations(100)
    .warmup(10)
    .run()?;

println!("Mean: {} ns", report.samples.iter()
    .map(|s| s.duration_ns)
    .sum::<u64>() / report.samples.len() as u64);

§Using BenchSpec Directly

use mobench_sdk::{BenchSpec, run_benchmark};

let spec = BenchSpec {
    name: "my_benchmark".to_string(),
    iterations: 50,
    warmup: 5,
};

let report = run_benchmark(spec)?;
println!("Collected {} samples", report.samples.len());

§Discovering Benchmarks

use mobench_sdk::{discover_benchmarks, list_benchmark_names};

// Get all registered benchmark names
let names = list_benchmark_names();
for name in names {
    println!("Found benchmark: {}", name);
}

// Get full benchmark function info
let benchmarks = discover_benchmarks();
for bench in benchmarks {
    println!("Benchmark: {}", bench.name);
}

§Building Mobile Apps

The SDK includes builders for automating mobile app creation:

§Android Builder

use mobench_sdk::builders::AndroidBuilder;
use mobench_sdk::{BuildConfig, BuildProfile, Target};

let builder = AndroidBuilder::new(".", "my-bench-crate")
    .verbose(true)
    .output_dir("target/mobench");  // Default

let config = BuildConfig {
    target: Target::Android,
    profile: BuildProfile::Release,
    incremental: true,
};

let result = builder.build(&config)?;
println!("APK built at: {:?}", result.app_path);

§iOS Builder

use mobench_sdk::builders::{IosBuilder, SigningMethod};
use mobench_sdk::{BuildConfig, BuildProfile, Target};

let builder = IosBuilder::new(".", "my-bench-crate")
    .verbose(true);

let config = BuildConfig {
    target: Target::Ios,
    profile: BuildProfile::Release,
    incremental: true,
};

let result = builder.build(&config)?;
println!("xcframework built at: {:?}", result.app_path);

// Package IPA for distribution
let ipa_path = builder.package_ipa("BenchRunner", SigningMethod::AdHoc)?;

§Output Directory

By default, all mobile artifacts are written to target/mobench/:

target/mobench/
├── android/
│   ├── app/
│   │   ├── src/main/jniLibs/     # Native .so libraries
│   │   └── build/outputs/apk/    # Built APK
│   └── ...
└── ios/
    ├── sample_fns.xcframework/   # Built xcframework
    ├── BenchRunner/              # Xcode project
    └── BenchRunner.ipa           # Packaged IPA

This keeps generated files inside target/, following Rust conventions and preventing accidental commits of mobile project files.

§Platform Requirements

§Android

  • Android NDK (set ANDROID_NDK_HOME environment variable)
  • cargo-ndk (cargo install cargo-ndk)
  • Rust targets: rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android

§iOS

  • Xcode with command line tools
  • uniffi-bindgen (cargo install uniffi-bindgen)
  • xcodegen (optional, brew install xcodegen)
  • Rust targets: rustup target add aarch64-apple-ios aarch64-apple-ios-sim

§Best Practices

§Use black_box to Prevent Optimization

Always wrap benchmark results with std::hint::black_box to prevent the compiler from optimizing away the computation:

#[benchmark]
fn correct_benchmark() {
    let result = expensive_computation();
    std::hint::black_box(result);  // Result is "used"
}

§Avoid Side Effects

Benchmarks should be deterministic and avoid I/O operations:

// Good: Pure computation
#[benchmark]
fn good_benchmark() {
    let data = vec![1, 2, 3, 4, 5];
    let sum: i32 = data.iter().sum();
    std::hint::black_box(sum);
}

// Avoid: File I/O adds noise
#[benchmark]
fn noisy_benchmark() {
    let data = std::fs::read_to_string("data.txt").unwrap();  // Don't do this
    std::hint::black_box(data);
}

§Choose Appropriate Iteration Counts

  • Warmup: 5-10 iterations to warm CPU caches and JIT
  • Iterations: 50-100 for stable statistics
  • Mobile devices may have more variance than desktop

§Feature Flags

Currently, mobench-sdk has no optional feature flags. All functionality is included by default.

§License

MIT License - see repository for details.

Re-exports§

pub use registry::BenchFunction;
pub use registry::discover_benchmarks;
pub use registry::find_benchmark;
pub use registry::list_benchmark_names;
pub use runner::BenchmarkBuilder;
pub use runner::run_benchmark;
pub use types::BenchError;
pub use types::BuildConfig;
pub use types::BuildProfile;
pub use types::BuildResult;
pub use types::InitConfig;
pub use types::Target;
pub use mobench_runner;

Modules§

builders
Build automation for mobile platforms
codegen
Code generation and template management
registry
Benchmark function registry
runner
Benchmark execution runtime
types
Core types for mobench-sdk.

Structs§

BenchSample
A single timing sample from a benchmark iteration.
BenchSpec
Benchmark specification defining what and how to benchmark.
RunnerReport
Complete benchmark report with all timing samples.

Constants§

VERSION
Library version, matching Cargo.toml.

Attribute Macros§

benchmark
Marks a function as a benchmark for mobile execution.