Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Multiplatform Performance Benchmarking

This is the source code for the apps described in the article: Comparing Benchmark Performance of Mobile Multiplatform Tools

Guide to Running the Apps Locally

This repo contains three implementations of the same app, used to compare performance:

  • amp/ — Kotlin Multiplatform + Compose Multiplatform (KMP/CMP)
  • react-native/ — React Native
  • flutter/ — Flutter

All three apps run in release mode (optimized, no dev/debug overhead) on an Android emulator and an iOS Simulator, all from the command line — no Android Studio or Xcode GUI required. Release builds in this repo reuse the debug keystore / are unsigned for local benchmarking only — do not reuse these signing configs for anything distributed to users.

Exception: Flutter does not ship release/profile-mode engine binaries for the iOS Simulator target (Dart AOT snapshots are only built for physical-device architectures) — flutter build ios --release --simulator fails with "Release mode is not supported for simulators". This is a Flutter platform limitation, not a project configuration issue. The Flutter app's Android build is still full release mode; its iOS Simulator build necessarily runs in debug mode. A true release-mode Flutter/iOS comparison would require a physical device.

Prerequisites

  • Android: Android SDK installed, with $ANDROID_HOME set and platform-tools/emulator on your PATH (or use the full paths under $ANDROID_HOME). At least one AVD created (Android Studio's Device Manager, or avdmanager).
  • iOS: Xcode installed, with at least one Simulator runtime available.
  • React Native only: Node.js (>= 22.11.0), and Ruby/Bundler for CocoaPods.
  • Flutter only: Flutter SDK on PATH (e.g. brew install --cask flutter), with flutter doctor reporting no blocking issues for Android and iOS.

Start an Android emulator (if none is running)

adb devices                      # check if one is already running
emulator -list-avds              # list available AVDs
emulator -avd <avd-name> &       # boot one, e.g. Pixel_9_Pro_XL_API_36.1

Boot an iOS Simulator (if none is running)

xcrun simctl list devices | grep Booted   # check if one is already running
xcrun simctl list devices available       # list available simulators
xcrun simctl boot "iPhone 16"             # boot one by name
open -a Simulator                          # bring up the Simulator UI

amp/ — Kotlin Multiplatform app

Bundle/application id: com.multiplatformperf.amp

Android (release)

cd amp
./gradlew :androidApp:installRelease
adb shell am start -n com.multiplatformperf.amp/com.multiplatformperf.amp.MainActivity

iOS Simulator (release)

Build with a deterministic output path (-derivedDataPath build) so the app path below is predictable:

cd amp
xcodebuild -project iosApp/iosApp.xcodeproj -scheme iosApp -configuration Release \
  -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 16' \
  -derivedDataPath build \
  build

xcrun simctl install booted build/Build/Products/Release-iphonesimulator/iosApp.app
xcrun simctl launch booted com.multiplatformperf.amp

Replace platform=iOS Simulator,name=iPhone 16 with the name (or id=<UDID>) of whichever simulator you booted above. booted in the simctl commands targets whichever simulator is currently running — swap in an explicit UDID if you have more than one booted at once.


react-native/ — React Native app

Application id (Android) / bundle id (iOS): com.multiplatformperf.rn

One-time setup:

cd react-native
npm install
bundle install
bundle exec pod install --project-directory=ios

Android (release)

cd react-native
npx react-native run-android --mode=release

This builds, installs, and launches the release variant on whichever emulator/device adb sees.

iOS Simulator (release)

cd react-native
npx react-native run-ios --mode Release --simulator "iPhone 16"

This builds, installs, and launches the Release configuration on the named simulator (boots it if it isn't already running). Swap "iPhone 16" for any simulator name from xcrun simctl list devices available.


flutter/ — Flutter app

Application id (Android) / bundle id (iOS): com.multiplatformperf.flutter

One-time setup:

cd flutter
flutter pub get

Android (release)

cd flutter
flutter build apk --release
adb install -r build/app/outputs/flutter-apk/app-release.apk
adb shell am start -n com.multiplatformperf.flutter/com.multiplatformperf.flutter.MainActivity

iOS Simulator (debug only — see exception above)

Flutter has no release/profile build for the Simulator target, so this runs in debug mode:

cd flutter
flutter build ios --debug --simulator
xcrun simctl install booted build/ios/iphonesimulator/Runner.app
xcrun simctl launch booted com.multiplatformperf.flutter

Verifying a run without opening the simulator/emulator window

# Android — check the app process is alive
adb shell pidof com.multiplatformperf.amp   # or com.multiplatformperf.rn / com.multiplatformperf.flutter

# iOS — simctl launch prints the PID on success
xcrun simctl launch booted com.multiplatformperf.amp   # or com.multiplatformperf.rn / com.multiplatformperf.flutter

About

A Performance Benchmark Test App to compare 3 popular multi-platform development tools

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages