mobench
Mobile benchmarking CLI for Rust - Run benchmarks on real Android and iOS devices.
The mobench CLI is the easiest way to benchmark your Rust code on mobile devices. It handles everything from project setup to building mobile apps to running tests on real devices via BrowserStack.
Installation
Or build from source:
Use as a Cargo subcommand:
Quick Start
1. Initialize Your Project
# Create mobile benchmarking setup for Android
# Or for iOS
# Or for both platforms
This creates:
bench-mobile/- FFI wrapper crate with UniFFI bindingsandroid/orios/- Platform-specific app projects (generated to output directory)bench-config.toml- Run configuration filemobench.toml- Project configuration file (when usinginit)benches/example.rs- Example benchmarks (with--examples)
2. Write Benchmarks
// benches/my_benchmarks.rs
use benchmark;
3. Build for Mobile
# Build Android APK
# Build iOS app
4. Run Benchmarks
Local device workflow (builds artifacts and writes the run spec; launch the app manually):
On real devices via BrowserStack:
Note: Always use the --release flag for BrowserStack runs. Debug builds are significantly larger (~544MB vs ~133MB for release) and may cause upload timeouts.
Commands
init - Initialize Project
Create mobile benchmarking infrastructure:
Options:
--target <android|ios|both>- Target platform (default: android)--output <FILE>- Config file path (default: bench-config.toml)
Example:
build - Build Mobile Apps
Cross-compile and package for mobile platforms:
|
Options:
--target <android|ios>- Platform to build for (required)--release- Build in release mode (default: debug)--output-dir <DIR>- Output directory for mobile artifacts (default:target/mobench/)--crate-path <PATH>- Path to the benchmark crate (default: auto-detect)--dry-run- Print what would be done without making changes--verbose/-v- Print verbose output including all commands
Examples:
# Build Android APK in release mode
# Build iOS xcframework
# Preview build without making changes
# Build with verbose output
# Build to custom output directory
Outputs:
- Android:
target/mobench/android/app/build/outputs/apk/debug/app-debug.apk - iOS:
target/mobench/ios/sample_fns.xcframework
run - Run Benchmarks
Execute benchmarks on devices:
|
Options:
--target <android|ios>- Platform (required)--function <NAME>- Benchmark function name (required)--iterations <N>- Number of iterations (default: 100)--warmup <N>- Warmup iterations (default: 10)--devices <LIST>- Comma-separated device list for BrowserStack--device-matrix <FILE>- Load devices from a matrix YAML file (overridesdevice_matrixfrom--configwhen both are provided)--device-tags <TAG>- Filter device matrix by tag (repeatable / comma-separated)--local-only- Skip mobile builds (no device run)--config <FILE>- Load run spec from config file--ios-app <FILE>- iOS .ipa or zipped .app for BrowserStack--ios-test-suite <FILE>- iOS XCUITest runner (.zip or .ipa)--output <FILE>- Save results to JSON file (default: target/mobench/results.json)--summary-csv- Write CSV summary alongside JSON/Markdown--fetch- Fetch BrowserStack results after completion--ci- CI mode (step summary + regression exit codes)--baseline <path|url|artifact:<path>>- Compare against baseline summary (non-zero on regressions); if baseline resolves to the output file path, mobench snapshots the previous file first--regression-threshold-pct <N>- Regression threshold percentage (default: 5.0)--junit <FILE>- Write JUnit XML report
Outputs:
- JSON summary (default:
target/mobench/results.json) - Markdown summary (same base name,
.md) - CSV summary (same base name,
.csv, when--summary-csvis set)
Examples:
# Run locally (no BrowserStack devices specified)
# Run on BrowserStack devices (use --release for smaller APK)
# Run on iOS with auto-fetch (use --release for smaller artifacts)
ci run - One-command CI Orchestration
Run build/package/run/fetch/report end-to-end with stable CI output files:
||
Contract outputs (default directory: target/mobench/ci/):
summary.jsonsummary.mdresults.csv
summary.json includes a ci section with metadata fields:
requested_bypr_numberrequest_commandmobench_refmobench_versiontrigger_sourcedispatch_id
Contract references:
docs/CONTRACT_CI_V1.mddocs/schemas/summary-v1.schema.jsondocs/schemas/ci-contract-v1.schema.json
When ci run is wrapped by the reusable GitHub workflow used in the 0.1.16 webhook flow, the canonical mobench-history-v1 bundle also stores per-platform workflow_inputs metadata such as base_ref and regression_threshold_pct for exact reruns and server-side comparisons.
Example:
# Combined android + ios contract output
When --baseline is omitted for ci run, mobench automatically uses the previous successful summary snapshot in the target output directory when present.
config validate - Validate Run Config Contract
Validate bench-config.toml and referenced matrix/settings with contract-aligned issue categories:
devices resolve - Deterministic Matrix Resolution
Resolve matrix devices for a platform/profile without custom scripts:
fixture - Fixture Lifecycle Commands
Manage reproducible fixture setup for CI:
# Create starter fixture files
# Build fixture artifacts
# Verify fixture config + matrix resolution
# Generate deterministic cache key
package-ipa - Package iOS IPA
Create a signed IPA for BrowserStack:
Options:
--scheme <NAME>- Xcode scheme (default: BenchRunner)--method <adhoc|development>- Signing method (default: adhoc)
Example:
Output: target/mobench/ios/BenchRunner.ipa
package-xcuitest - Package XCUITest Runner
Create the XCUITest runner package required for BrowserStack iOS testing:
Options:
--scheme <NAME>- Xcode scheme for UI tests (default: BenchRunnerUITests)
Example:
Output: target/mobench/ios/BenchRunnerUITests.zip
This command builds the XCUITest target and packages it into the zip format that BrowserStack expects for iOS test automation.
plan - Generate Device Matrix
Create a template device matrix file:
Example:
Output: device-matrix.yaml
devices:
- name: Google Pixel 7-13.0
os: android
os_version: "13.0"
tags:
- name: iPhone 14-16
os: ios
os_version: "16"
tags:
list - List Benchmarks
Show benchmarks discovered via #[benchmark]:
fetch - Fetch Results
Download BrowserStack build artifacts:
|
Options:
--target <android|ios>- Platform (required)--build-id <ID>- BrowserStack build ID (required)--output-dir <DIR>- Download directory (default: target/browserstack)
Example:
compare - Compare Summaries
Compare two JSON run summaries and emit a Markdown report:
report summarize - Render CI Summary Markdown
Generate natural-language markdown from standardized output JSON:
report github - Sticky PR Comment Payload/Publish
Create or update sticky PR comments from standardized outputs:
# Print comment body
# Publish/update comment (requires GITHUB_TOKEN + GITHUB_REPOSITORY)
Configuration
Project Configuration (mobench.toml)
mobench automatically loads mobench.toml from the current directory or any parent directory:
[]
# Name of the benchmark crate
= "bench-mobile"
# Rust library name (typically crate name with hyphens replaced by underscores)
= "bench_mobile"
# Output directory for build artifacts (default: target/mobench/)
# output_dir = "target/mobench"
[]
# Android package name
= "com.example.bench"
# Minimum Android SDK version (default: 24)
= 24
# Target Android SDK version (default: 34)
= 34
[]
# iOS bundle identifier
= "com.example.bench"
# iOS deployment target version (default: 15.0)
= "15.0"
# Development team ID for code signing (optional)
# team_id = "YOUR_TEAM_ID"
[]
# Default benchmark function to run
= "my_crate::my_benchmark"
# Default number of benchmark iterations
= 100
# Default number of warmup iterations
= 10
CLI flags always override config file values when provided.
Run Config File Format (bench-config.toml)
For BrowserStack runs, you can also use a separate run configuration:
= "android"
= "sample_fns::fibonacci"
= 100
= 10
= "device-matrix.yaml"
= ["default"] # optional; filter devices by tag
[]
= "${BROWSERSTACK_USERNAME}"
= "${BROWSERSTACK_ACCESS_KEY}"
= "my-project-benchmarks"
[]
= "target/mobench/ios/BenchRunner.ipa"
= "target/mobench/ios/BenchRunnerUITests.zip"
Device Matrix Format (device-matrix.yaml)
devices:
- name: "Google Pixel 7-13.0"
os: "android"
os_version: "13.0"
tags:
- name: "iPhone 14-16"
os: "ios"
os_version: "16"
tags:
Environment Variables
BrowserStack credentials can be provided via:
-
Environment variables (recommended):
-
.env.localfile:BROWSERSTACK_USERNAME=your_username BROWSERSTACK_ACCESS_KEY=your_access_key -
Config file with variable expansion:
[] = "${BROWSERSTACK_USERNAME}" = "${BROWSERSTACK_ACCESS_KEY}"
Requirements
For Android
- Android NDK - Set
ANDROID_NDK_HOMEenvironment variable - cargo-ndk - Install with
cargo install cargo-ndk - Android SDK - API level 24+ required
- Gradle - For building APKs (bundled with Android project)
For iOS
- macOS with Xcode installed
- Xcode Command Line Tools -
xcode-select --install - Rust iOS targets:
- XcodeGen - Install with
brew install xcodegen
For BrowserStack
- BrowserStack App Automate account - Sign up
- Credentials - Username and access key from account settings
Examples
Benchmark Crypto Operations
# Initialize
# Add benchmark
# Build
# Run on multiple devices (use --release for BrowserStack)
Compare iOS Performance
# Run same benchmark on different iOS versions (use --release for BrowserStack)
CI Integration
Generate a ready-to-edit workflow + action wrapper:
This writes .github/workflows/mobile-bench.yml plus a local action in
.github/actions/mobench/ that handles caching, Android setup, and artifact upload.
Example workflow excerpt:
- uses: ./.github/actions/mobench
with:
command: cargo mobench ci run
run-args: |
--target android
--function my_benchmark
--devices "Google Pixel 7-13.0"
--iterations 50
--release
--fetch
ci: false
env:
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
The local action currently supports command values cargo mobench ci run and cargo mobench run.
For CI dashboards, add --junit path/to/results.junit.xml.
Typed Rust API
mobench also exposes a typed request/result surface for integrations:
use ;
use PathBuf;
let result = run_request?;
println!;
Workflow
┌─────────────────────┐
│ 1. cargo mobench │
│ init │
└──────────┬──────────┘
│
↓
┌─────────────────────┐
│ 2. Write benchmarks │
│ with #[benchmark]│
└──────────┬──────────┘
│
↓
┌─────────────────────┐
│ 3. cargo mobench │
│ build │
└──────────┬──────────┘
│
↓
┌─────────────────────┐
│ 4. cargo mobench │
│ run │
└──────────┬──────────┘
│
┌────┴────┐
↓ ↓
┌──────────┐ ┌──────────────┐
│ Local │ │ BrowserStack │
│ Emulator │ │ Real Devices │
└──────────┘ └──────────────┘
Troubleshooting
Android NDK not found
Or install via Android Studio: Tools → SDK Manager → SDK Tools → NDK
iOS code signing issues
For BrowserStack testing, use ad-hoc signing:
BrowserStack authentication failed
Verify credentials:
Or check .env.local file exists and contains valid credentials.
Benchmark function not found
Ensure:
- Function has
#[benchmark]attribute - Function is compiled into the mobile binary
- Function name matches exactly (case-sensitive)
Part of mobench
This CLI is part of the mobench ecosystem:
- mobench - This crate (CLI tool)
- mobench-sdk - Core SDK with timing harness, build automation, and codegen
- mobench-macros -
#[benchmark]proc macro
See Also
- mobench-sdk Documentation for programmatic API
- BrowserStack App Automate for device cloud
- UniFFI Documentation for FFI details
License
Licensed under the MIT License. See LICENSE.md for details.
Copyright (c) 2026 World Foundation