Build the first runner
Install the CLI, register one benchmark, and verify the generated Android artifacts.
Open the quickstart404 / DOCS ROUTE MISSING
The guide may have moved. Start at the documentation index or use search from any documentation page.
404 / route missing
The page may have moved to the canonical documentation host.
Stable release {site.release}
+mobench turns annotated Rust functions into Android and iOS runners, executes ordinary benchmarks on BrowserStack devices, and writes reviewable CI results.
+Current stable: local ordinary runs are build and host-preflight only. Local native profiling is supported separately.
+ + cargo install mobench --version {site.crateVersion}
+
+ Fixture-shaped output · remote Android execution
+Designed around the tools mobile Rust teams already ship with
+Capability truth
mobench has three distinct paths today: mobile artifact builds, hosted ordinary benchmark execution, and local native profiling. Treating those as one “local run” hides important differences.
+| Capability | Execution mode | {site.release} |
|---|---|---|
| {row.capability} | {row.mode} | {row.status} |
Why this is explicit: --local-only skips the mobile build and writes host-side preflight/spec output. It does not execute or measure a benchmark.
The working loop
Keep the benchmark beside the Rust code. The macro registers it; the SDK owns timing and result types.
+#[benchmark]
+pub fn verify_proof() {
+ black_box(run());
+}
+ Benchmark authoring
+ Build Android APK/test APK outputs or iOS runner artifacts with the platform toolchain.
+$ mobench build \
+ --target android \
+ --release
+ Build requirements
+ Supplying a device selects the BrowserStack ordinary execution path in the current stable release.
+$ mobench run \
+ --target android \
+ --function crate::verify_proof \
+ --devices "Google Pixel 8-14.0"
+ BrowserStack setup
+ CI mode writes machine-readable data and a Markdown summary into a predictable output directory.
+$ mobench ci run \
+ --target android \
+ --function crate::verify_proof \
+ --devices "Google Pixel 8-14.0" \
+ --output-dir target/mobench/ci
+ Report artifacts
+ Evidence, not decoration
+This example is rendered from the checked-in examples/fixtures/basic/summary.json fixture in {site.release}. It demonstrates report shape and is not a product performance claim.
summary.jsonautomation and downstream toolingsummary.mdpull requests and human reviewresults.csvanalysis and dashboards| Device | Benchmark | Median | p95 |
|---|---|---|---|
| {row.device} | {row.benchmark} | {row.median} ms | {row.p95} ms |
Fixture data · values are intentionally deterministic for contract testing.
+A concrete workload shape
+ProveKit is an open-source Rust proving system with Swift, Kotlin, and C-compatible FFI surfaces. World ID documents the product context where proof technology reaches mobile users. Together they illustrate why a host-only timing number is incomplete: compilation target, FFI, mobile scheduling, and device constraints all sit on the real execution path.
+Source-backed context only. Mobench makes no device-coverage or performance claim from these links.
+Pick the task
Install the CLI, register one benchmark, and verify the generated Android artifacts.
Open the quickstartConfigure credentials and move from generated artifacts to an ordinary benchmark on remote hardware.
Set up the first runUse the narrower Android native or iOS Instruments path to generate capture and flamegraph artifacts.
Read profiling scopeBefore you build
mobench orchestrates the work; it does not replace the Android or Apple toolchains. Install only the path you need.
mobench {site.crateVersion}mobench-sdk and benchmark macroANDROID_NDK_HOMEcargo-ndkOne ecosystem, clear boundaries
Focused answers
Need command-level detail? The documentation is generated as static HTML and stays usable without client JavaScript.
Browse all documentation{answer}
Ready when the toolchain is
Privacy
Mobench may collect aggregate page and interaction counts to understand whether documentation paths work. Analytics events use fixed names and non-identifying properties.
Links to GitHub, docs.rs, BrowserStack, and World Foundation leave this site and follow those services’ privacy terms.
404
-
- No Mobench docs page matches /{slug}.
-
404
-That URL does not match an existing Mobench page.
-cargo mobench CLImobench-sdkmobench-macros#[benchmark] functions through inventory.>,
- <>Stable output artifacts: JSON summaries, Markdown summaries, CSV rows, optional plots, profiling manifests, trace-event JSON, and flamegraph bundles.>,
- ],
- },
- {
- title: 'How the pieces fit',
- body: [
- <>The CLI resolves project configuration, builds generated Android or iOS runner projects, invokes a local or hosted provider, fetches artifacts, and writes normalized reports. The SDK owns benchmark execution, timing, registry lookup, setup and teardown handling, runner reports, and public types.>,
- ],
- code: {
- language: 'text',
- value: `benchmark crate
- -> mobench-sdk registry and timing
- -> generated Android / iOS runner
- -> local device, emulator, simulator, host-only, or BrowserStack provider
- -> summary.json, summary.md, results.csv, plots, profile artifacts`,
- },
- },
- {
- title: 'Where to go next',
- bullets: [
- <>Start with Quickstart for the smallest working path.>,
- <>Use Local devices when you want connected phones, Android Studio emulators, ADB, Xcode simulators, or connected iOS devices.>,
- <>Use BrowserStack CI for hosted real-device runs and PR reporting.>,
- <>Use Outputs, Schemas, and Examples when wiring downstream tooling.>,
- ],
- },
- {
- title: 'External AI documentation',
- body: [
- <>
- DeepWiki by Cognition indexes the upstream repository into an external technical wiki that can be used as AI-readable context for Devin and other coding assistants. Use it when you want repo-wide navigation, source-linked explanations, or a fast second view beside these authored docs.
- >,
- ],
- bullets: [
- <>
- DeepWiki overview summarizes purpose, crate architecture, generated runner flow, reporting, and native profiling.
- >,
- <>
- DeepWiki index exposes the topic map for system architecture, CLI, SDK, macros, BrowserStack, templates, profiling, CI, examples, dependencies, and glossary pages.
- >,
- <>The “Copy page” action copies this authored page or sends it to an assistant; pair that with DeepWiki when you want an AI to answer from both local docs and source-indexed context.>,
- ],
- },
- ],
- quickstart: [
- {
- title: 'Command path',
- body: [
- <>The fast path is install, initialize config, check prerequisites, build a target runner, then run locally or through a provider.>,
- ],
- code: {
- language: 'bash',
- value: `cargo install mobench
-cargo mobench init
-cargo mobench doctor
-cargo mobench build --target android --release
-cargo mobench run --local --function fibonacci_30 --iterations 100 --warmup 10
-cargo mobench ci run --target android --browserstack --output target/mobench/ci`,
- },
- },
- {
- title: 'Local targets',
- body: [
- <>Local does not only mean a physical phone. Android can run through connected devices or Android emulators managed by Android Studio and ADB. iOS can run through Xcode-managed simulators or connected iOS devices. BrowserStack is the hosted-device path, useful for shared CI and reproducible remote devices.>,
- ],
- },
- {
- title: 'First benchmark',
- code: {
- language: 'rust',
- value: `use mobench_sdk::benchmark;
-
-#[benchmark]
-pub fn fibonacci_30() {
- let result = fibonacci(30);
- std::hint::black_box(result);
-}
-
-fn setup_data() -> Vecrustup. Use Rust 2024-compatible toolchains; current workspace release line is 0.1.43 and documented MSRV is Rust 1.85.>,
- <>Install CLI cargo install mobench or build from repository when developing mobench itself.>,
- <>Add mobench-sdk, inventory, and required crate types to benchmark crates.>,
- ],
- code: {
- language: 'toml',
- value: `[dependencies]
-mobench-sdk = "0.1.43"
-inventory = "0.3"
-
-[lib]
-crate-type = ["cdylib", "staticlib", "lib"]`,
- },
- },
- {
- title: 'Android and iOS',
- bullets: [
- <>cargo mobench check --target android and cargo mobench check --target ios before chasing build failures.>,
- ],
- },
- {
- title: 'BrowserStack credentials',
- body: [
- <>mobench: CLI, BrowserStack client, CI and reporting entry points, and programmatic command types.>,
- <>mobench-sdk: timing harness, benchmark registry, generated runner support, mobile builders, profiling helpers, UniFFI, and native C ABI.>,
- <>mobench-macros: the #[benchmark] proc macro.>,
- ],
- },
- {
- title: 'Artifact flow',
- body: [
- <>Runs produce normalized artifacts under target/mobench/. BrowserStack fetches also place raw provider artifacts under a BrowserStack output root. Profiling creates trace events and flamegraph-ready bundles.>,
- ],
- },
- ],
- authoring: [
- {
- title: 'Macro shape',
- body: [
- <>Simple benchmark functions take no parameters, return (), and should use std::hint::black_box for values the optimizer might otherwise erase.>,
- ],
- code: {
- language: 'rust',
- value: `use mobench_sdk::benchmark;
-
-#[benchmark]
-pub fn checksum_bench() {
- let data = [1u8; 1024];
- let sum: u64 = data.iter().map(|b| *b as u64).sum();
- std::hint::black_box(sum);
-}`,
- },
- },
- {
- title: 'Discovery',
- bullets: [
- <>Benchmarks are registered at compile time through inventory.>,
- <>Generated runners discover registered functions through SDK registry APIs.>,
- <>Macro validation rejects unsupported signatures early, including parameters on simple benchmarks or non-unit returns.>,
- ],
- },
- {
- title: 'Best practices',
- bullets: [
- <>Keep input generation outside measured work unless the input generation is itself what you are benchmarking.>,
- <>Use per-iteration setup for mutable or consumed input.>,
- <>Prefer stable iterations and warmup settings in config so CI reports are comparable.>,
- ],
- },
- ],
- 'setup-teardown': [
- {
- title: 'Setup modes',
- body: [
- <>Setup runs before measured samples and passes the setup value into the benchmark. Per-iteration setup runs before each measured iteration and is useful for mutable input.>,
- ],
- code: {
- language: 'rust',
- value: `fn create_input() -> VecBenchSpec names the benchmark and sets measured iterations and warmup iterations.>,
- <>BenchSample records wall-clock duration plus optional CPU and memory measurements.>,
- <>BenchReport contains samples, statistics helpers, semantic phases, and timeline spans.>,
- <>Target, FfiBackend, builders, and runner report types shape generated runner behavior.>,
- ],
- },
- {
- title: 'Choosing an FFI backend',
- body: [
- <>If you need generated bindings, choose between cargo mobench check for target-specific diagnostics before build commands.>,
- ],
- },
- {
- title: 'Build commands',
- code: {
- language: 'bash',
- value: `cargo mobench check --target android
-cargo mobench check --target ios
-cargo mobench build --target android --progress
-cargo mobench build --target ios --progress
-cargo mobench build --target both --release`,
- },
- },
- {
- title: 'Outputs',
- bullets: [
- <>Android builds produce generated projects, APK or test APK artifacts, native libraries, and runner metadata.>,
- <>iOS builds produce generated Xcode projects, simulator and device slices, test bundles, and runner metadata.>,
- <>Outputs default to target/mobench/; release builds are smaller and better suited for uploads.>,
- ],
- },
- ],
- 'local-devices': [
- {
- title: 'Android',
- bullets: [
- <>Use physical phones through ADB when you need device-specific CPU, memory, thermal, or ABI behavior.>,
- <>Use Android Studio emulators for fast local iteration, SDK compatibility checks, and repeatable development smoke runs.>,
- <>ADB is the local control layer for listing devices, installing generated APKs, and running generated Android test harnesses.>,
- ],
- code: {
- language: 'bash',
- value: `adb devices
-cargo mobench build --target android
-cargo mobench run --target android --local --function my_crate::checksum_bench`,
- },
- },
- {
- title: 'iOS',
- bullets: [
- <>Use Xcode simulators for local iteration without requiring a physical iPhone.>,
- <>Use connected iOS devices when hardware behavior, signing, device OS version, or performance fidelity matters.>,
- <>Xcode owns simulator runtimes, device trust, signing, summary.json, summary.md, and results.csv.>,
- <>PR reporting can post sticky summaries and compare baselines.>,
- <>Fetch commands retrieve raw BrowserStack artifacts after hosted runs.>,
- <>Use ci run job, store the outputs as sample-*/summary.json, then merge them back into the standard CI contract.>,
- ],
- bullets: [
- <>Every input must contain exactly one device, one benchmark, and one measured sample.>,
- <>The command validates the requested function, device, target consistency, and exact measured sample count.>,
- <>Merged timing statistics, raw samples_ns, and resource columns are recomputed for downstream reports, plots, comparisons, and PR comments.>,
- ],
- code: {
- language: 'bash',
- value: `cargo mobench ci merge-split-runs \\
- --samples-dir target/mobench/ci/android/sample_fns__fibonacci/device/split \\
- --output-dir target/mobench/ci/android/sample_fns__fibonacci/device \\
- --function sample_fns::fibonacci \\
- --device "Google Pixel 7-13.0" \\
- --iterations 5 \\
- --warmup 1`,
- },
- },
-],
-'app-automate': [
- {
- title: 'Account and pricing',
- body: [
- <>.apk or .aab to POST /app-automate/espresso/v2/app.>,
- <>Upload Espresso test suite APK to POST /app-automate/espresso/v2/test-suite.>,
- <>Start execution with POST /app-automate/espresso/v2/build, passing app, testSuite, and Android devices.>,
- ],
- code: {
- language: 'bash',
- value: `# Upload Android app
-curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \\
- -X POST "https://api-cloud.browserstack.com/app-automate/espresso/v2/app" \\
- -F "file=@target/mobench/android/app-release.apk" \\
- -F "custom_id=mobench-android-app"
-
-# Upload Espresso test APK
-curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \\
- -X POST "https://api-cloud.browserstack.com/app-automate/espresso/v2/test-suite" \\
- -F "file=@target/mobench/android/app-release-androidTest.apk" \\
- -F "custom_id=mobench-android-tests"
-
-# Start an Espresso build
-curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \\
- -X POST "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" \\
- -H "Content-Type: application/json" \\
- -d '{"app":"mobench-android-app","testSuite":"mobench-android-tests","project":"mobench","devices":["Google Pixel 7-13.0"]}'`,
- },
- },
- {
- title: 'XCUITest on iOS',
- body: [
- <>.ipa to POST /app-automate/xcuitest/v2/app.>,
- <>Upload XCUITest suite as .zip to POST /app-automate/xcuitest/v2/test-suite.>,
- <>Start execution with POST /app-automate/xcuitest/v2/build, passing app, testSuite, and iOS devices.>,
- ],
- code: {
- language: 'bash',
- value: `# Upload iOS app
-curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \\
- -X POST "https://api-cloud.browserstack.com/app-automate/xcuitest/v2/app" \\
- -F "file=@target/mobench/ios/MobenchRunner.ipa" \\
- -F "custom_id=mobench-ios-app"
-
-# Upload XCUITest bundle
-curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \\
- -X POST "https://api-cloud.browserstack.com/app-automate/xcuitest/v2/test-suite" \\
- -F "file=@target/mobench/ios/MobenchRunnerUITests.zip" \\
- -F "custom_id=mobench-ios-tests"
-
-# Start an XCUITest build
-curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \\
- -X POST "https://api-cloud.browserstack.com/app-automate/xcuitest/v2/build" \\
- -H "Content-Type: application/json" \\
- -d '{"app":"mobench-ios-app","testSuite":"mobench-ios-tests","project":"mobench","devices":["iPhone 14-16"]}'`,
- },
- },
- {
- title: 'API lifecycle',
- body: [
- <>The https://api-cloud.browserstack.com/. The usual CI lifecycle uploads app and test-suite artifacts, creates a build, polls build or session status, fetches logs and media, then normalizes results into mobench summaries.>,
- ],
- bullets: [
- <>Authentication uses BrowserStack username and access key over basic auth.>,
- <>Uploads return bs://... URLs and optional custom_id aliases. Use custom IDs in CI when scripts should refer to the latest uploaded app or test suite without rewriting every build request.>,
- <>A build represents execution of a framework-specific test suite on one or more devices; BrowserStack returns build_id for status and artifact lookup.>,
- <>CI should avoid upload loops and respect BrowserStack API limits.>,
- ],
- code: {
- language: 'bash',
- value: `curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \\
- -X GET "https://api-cloud.browserstack.com/app-automate/devices.json"
-
-curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \\
- -X GET "https://api-cloud.browserstack.com/app-automate/espresso/v2/builds"
-
-curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \\
- -X GET "https://api-cloud.browserstack.com/app-automate/xcuitest/v2/builds"`,
- },
- },
- {
- title: 'Devices',
- body: [
- <>BrowserStack App Automate runs on physical devices hosted by BrowserStack, not emulators or simulators. Pick exact names and OS versions from GET /app-automate/devices.json when generating or validating mobench device matrices.>,
- <>The device API response includes OS, OS version, device name, real-device flag, tier, and limit fields.>,
- ],
- },
-],
-profiling: [
- {
- title: 'Capability matrix',
- bullets: [
- <>Local native profiling is the supported path for native stack capture and flamegraph-style artifacts.>,
- <>BrowserStack benchmark runs can still report timing and resource metrics, but native stack capture and flamegraph generation are local capabilities.>,
- <>Profile commands use the same target, device, matrix, and function concepts as benchmark runs.>,
- ],
- },
- {
- title: 'Artifacts',
- body: [
- <>Each profiling session writes a run-specific directory under target/mobench/profile/<run-id>/ and refreshes convenience copies under target/mobench/profile/.>,
- ],
- bullets: [
- <>profile.json: normalized manifest with capture metadata, native capture records, semantic phases, and viewer hints.>,
- <>summary.md: human-readable profile summary.>,
- <>artifacts/processed/stacks.folded: folded stack input used for flamegraph rendering.>,
- <>artifacts/processed/native-report.txt: backend-specific native profiling report.>,
- <>artifacts/processed/flamegraph.full.svg: full-process static flamegraph.>,
- <>artifacts/processed/flamegraph.focused.svg: benchmark-focused static flamegraph.>,
- <>artifacts/processed/flamegraph.html: interactive viewer with mode switching, timeline, search, selection, and legend controls.>,
- <>artifacts/semantic/phases.json: semantic phase data when benchmarks emit phase markers.>,
- ],
- code: {
- language: 'bash',
- value: `cargo mobench profile run \\
- --target android \\
- --function sample_fns::fibonacci \\
- --provider local \\
- --backend android-native \\
- --trace-events-output target/mobench/profile/trace-events.json
-
-cargo mobench profile summarize \\
- --profile target/mobench/profile/profile.json
-
-cargo mobench profile diff \\
- --baseline target/mobench/profile/baseline/profile.json \\
- --candidate target/mobench/profile/candidate/profile.json \\
- --normalize`,
- },
- },
- {
- title: 'Flamegraph viewer',
- body: [
- <>Open artifacts/processed/flamegraph.html after profile run or profile diff to inspect the interactive flamegraph. The viewer combines the full-process stack view, a benchmark-focused view, optional harness timeline spans, source-link metadata when symbolization can recover it, and a right-side self-time frame list.>,
- <>For differential profiles, red means a frame is hotter in the candidate profile and blue means it is hotter in the baseline. Frame widths follow candidate sample counts, so the widest red frames are usually the first places to inspect.>,
- ],
- bullets: [
- <>Benchmark Only: focus the flamegraph on frames below mobench benchmark anchors, hiding unrelated process/runtime work.>,
- <>Full Process: show all sampled stacks captured by the backend, useful for spotting runtime, FFI, allocator, or harness overhead.>,
- <>Timeline: show chronological harness spans such as warmup, measured benchmark iterations, teardown, and exact harness duration.>,
- <>Back, Forward, and Reset: navigate zoom history and return to the full root.>,
- <>Fullscreen: expand the viewer when frame labels or deep stacks need more room.>,
- <>Legend: explain color semantics, differential heat, and sample-width meaning.>,
- <>Search: find frames by function/module text, then zoom or inspect matching stacks.>,
- <>Self time: use the right rail to inspect the highest self-sample frames; click a frame in the graph to update selection details.>,
- ],
- image: {
- src: '/assets/flamegraph-viewer.png',
- alt: 'Screenshot of the mobench flamegraph viewer showing benchmark-only and full-process modes, timeline spans, search controls, and the self-time frame list.',
- caption: 'The generated flamegraph viewer lets you switch between benchmark-only and full-process views, inspect timeline spans, search stack frames, and use the self-time rail to find hot functions.',
- },
- code: {
- language: 'bash',
- value: `# Open the latest interactive viewer after profile run.
-open target/mobench/profile/artifacts/processed/flamegraph.html
-
-# Open a specific run's viewer.
-open target/mobench/profile/summary.json: normalized machine-readable summary.>,
- <>summary.md: human-readable run summary for CI and PR comments.>,
- <>results.csv: rows for spreadsheet and dashboard ingestion.>,
- <>Optional plot SVGs and profiling bundles live beside run outputs when requested.>,
- ],
- },
- {
- title: 'Split-run outputs',
- bullets: [
- <>Release 0.1.43 can merge sample-*/summary.json inputs from one-sample CI jobs into the same summary.json, summary.md, and results.csv contract.>,
- <>The merged JSON preserves raw samples, recomputes min, max, mean, median, and p95 timing statistics, and combines available resource measurements.>,
- <>Existing report, plot, comparison, and PR-comment tooling can consume merged output without a separate format adapter.>,
- ],
- },
- {
- title: 'Report helpers',
- code: {
- language: 'bash',
- value: `cargo mobench summary target/mobench/results.json
-cargo mobench summary --format json target/mobench/results.json
-cargo mobench summary --format csv target/mobench/results.json
-cargo mobench report summarize --summary target/mobench/ci/summary.json
-cargo mobench report github --pr 123 --summary target/mobench/ci/summary.json`,
- },
- },
- {
- title: 'Fixtures',
- body: [
- <>The repository examples include basic, FFI, and profiling fixtures so downstream tooling can validate summary and trace-event parsing without running device jobs.>,
- ],
- },
- ],
- 'cli-reference': [
- {
- title: 'Command model',
- body: [
- <>Use mobench directly, or cargo mobench when installed as a Cargo subcommand. Commands share the same global flags and most commands resolve project layout from explicit flags, config files, Cargo metadata, or workspace defaults.>,
- ],
- bullets: [
- <>--dry-run: print the actions that would run without mutating files, invoking providers, or publishing reports.>,
- <>-v / --verbose: print verbose command output and invoked tool commands.>,
- <>--yes: assume yes for overwrite prompts.>,
- <>--non-interactive: disable prompts and fail instead of asking.>,
- <>Common targets: android, ios, or both where supported. BrowserStack run targets use android or ios.>,
- <>Common output formats: text, json, csv, table, markdown, depending on command.>,
- ],
- code: {
- language: 'text',
- value: `mobench [GLOBAL OPTIONS] run for a one-off benchmark execution and ci run for the stable CI contract. Both can build mobile artifacts, run host-only smoke tests, target BrowserStack devices, fetch artifacts, compare baselines, and write machine-readable outputs.>,
- ],
- code: {
- language: 'text',
- value: `mobench run
-Purpose:
- Build, package, execute, and optionally fetch benchmark results for a single run.
-
-Usage:
- mobench run [OPTIONS]
-
-Inputs and flags:
- --target ci run for the actual benchmark execution contract.>,
- ],
- code: {
- language: 'text',
- value: `mobench ci init
-Purpose:
- Generate a GitHub Actions workflow and local action wrapper.
-Usage:
- mobench ci init [--workflow