This is the source code for the apps described in the article: Comparing Benchmark Performance of Mobile Multiplatform Tools
This repo contains three implementations of the same app, used to compare performance:
amp/— Kotlin Multiplatform + Compose Multiplatform (KMP/CMP)react-native/— React Nativeflutter/— 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.
- Android: Android SDK installed, with
$ANDROID_HOMEset andplatform-tools/emulatoron yourPATH(or use the full paths under$ANDROID_HOME). At least one AVD created (Android Studio's Device Manager, oravdmanager). - 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), withflutter doctorreporting no blocking issues for Android and iOS.
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.1xcrun 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 UIBundle/application id: com.multiplatformperf.amp
cd amp
./gradlew :androidApp:installRelease
adb shell am start -n com.multiplatformperf.amp/com.multiplatformperf.amp.MainActivityBuild 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.ampReplace 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.
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=ioscd react-native
npx react-native run-android --mode=releaseThis builds, installs, and launches the release variant on whichever emulator/device adb sees.
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.
Application id (Android) / bundle id (iOS): com.multiplatformperf.flutter
One-time setup:
cd flutter
flutter pub getcd 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.MainActivityFlutter 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# 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