flutter_plugin_startup_stress is an Android cold-startup benchmark app designed to stress Flutter's first-frame rendering pipeline alongside realistic async plugin initialization. Immediately upon runApp(), it renders a scene containing 14+ font styles across weights w200–w900, vector_graphics SVGs, decoded PNG textures, gradients, clips, elevation shadows, and color filters (requiring dozens of Impeller shader and pipeline variants) while concurrently initializing 13 common plugins (sqflite, shared_preferences, path_provider, device_info_plus, package_info_plus, connectivity_plus, battery_plus, url_launcher, webview_flutter, video_player, image_picker, sensors_plus, and share_plus).
The repository includes a CLI helper at tools/bin/tools.dart that automates building the profile APK against a local Flutter engine checkout, installing it onto an attached Android device, and capturing cold-startup Perfetto traces and verification screenshots.
-
Flutter checkout & local engine build: Build the Android arm64 profile engine and matching host profile engine in your
flutter/fluttercheckout:./engine/src/flutter/bin/et build -c android_profile_arm64 --no-rbe ./engine/src/flutter/bin/et build -c host_profile --no-rbe
(On Apple Silicon macOS hosts, build
host_profile_arm64instead ofhost_profile.) -
Attached Android device (
arm64): Connect an Android device with USB debugging enabled.tools.dartlocatesadbautomatically via$ANDROID_HOME/platform-toolsor$HOME/Android/Sdk/platform-tools(or you can pass--android-sdk). -
Resolve tool & app dependencies: From the root of
flutter_plugin_startup_stress:flutter pub get
Run all commands from the flutter_plugin_startup_stress root directory:
# 1. Build the profile APK using your local engine checkout
dart run tools/bin/tools.dart build \
--flutter-bin=/path/to/flutter/bin/flutter \
--local-engine-src-path=/path/to/flutter/engine/src \
--local-engine=android_profile_arm64 \
--local-engine-host=host_profile
# 2. Install the built profile APK onto the attached device
dart run tools/bin/tools.dart install
# 3. Cold-start the app, record a Perfetto trace + screenshot to data/, and uninstall
dart run tools/bin/tools.dart run baseline_run1Once run finishes, inspect the trace in the Perfetto UI by opening the generated file under data/:
data/flutter_startup_baseline_run1_<YYYYMMDD_HHMMSS>.perfetto-tracedata/flutter_startup_baseline_run1_<YYYYMMDD_HHMMSS>.png
Global option available on all commands:
--android-sdk=<path>: Path to the Android SDK root orplatform-toolsdirectory (overrides$ANDROID_HOMEand$HOME/Android/Sdk).
Builds build/app/outputs/flutter-apk/app-profile.apk in --profile mode against your local engine build.
dart run tools/bin/tools.dart build [arguments]| Option | Description | Default |
|---|---|---|
--flutter-bin |
Path to the flutter CLI executable. |
<defaultFlutterRoot>/bin/flutter |
--local-engine-src-path |
Path to the Flutter engine/src directory. |
<defaultFlutterRoot>/engine/src |
--local-engine |
Target local engine configuration name. | android_profile_arm64 |
--local-engine-host |
Host local engine configuration name (e.g. host_profile or host_profile_arm64). |
host_profile |
Installs the profile APK onto the connected Android device via adb install -r. Because run uninstalls the app at the end of each capture to guarantee a clean cold start, run install before each run invocation.
dart run tools/bin/tools.dart install [arguments]| Option | Description | Default |
|---|---|---|
--apk |
Path to the APK to install. | build/app/outputs/flutter-apk/app-profile.apk |
-d, --device |
Android device serial passed to adb -s (required when multiple devices are attached). |
(single attached device) |
--android-sdk |
Path to Android SDK or platform-tools. |
$ANDROID_HOME or $HOME/Android/Sdk |
Performs a clean cold-startup Perfetto trace capture and saves both the trace and a verification screenshot to data/.
Specifically, run executes the following steps in order:
- Force-stops the app (
adb shell am force-stop) so no warm process exists. - Starts an on-device
perfettosession (64 MiBbuffer) recording thetrack_event(Flutter/Impeller/Dart timeline slices) andlinux.ftrace(atrace_appsfor the package) data sources. - Waits 2 seconds for
tracedto activate, then cold-starts the activity viaadb shell am start -W -n ...(printing Android'sLaunchState,TotalTime, andWaitTime). - Waits for the trace session to complete (
--duration-ms, default10000ms). - Pulls
/data/misc/perfetto-traces/flutter_startup.perfetto-tracetodata/flutter_startup[_<suffix>]_<timestamp>.perfetto-trace. - Captures an on-device screenshot (
adb exec-out screencap -p) todata/flutter_startup[_<suffix>]_<timestamp>.png. - Force-stops and uninstalls the app from the device (unless
--wait-for-quit/-wis specified).
dart run tools/bin/tools.dart run [suffix] [arguments]| Option | Description | Default |
|---|---|---|
[suffix] or -s, --suffix |
Label inserted into the output trace and screenshot filenames (flutter_startup_<suffix>_<timestamp>). |
(none) |
--duration-ms |
Duration of the Perfetto trace session in milliseconds. | 10000 |
-w, --wait-for-quit |
Keep the app running after saving the trace and screenshot; blocks and ignores all other input until 'q' is pressed, then stops and uninstalls the app. |
false |
-d, --device |
Android device serial passed to adb -s. |
(single attached device) |
--package |
Android application package name to trace, launch, and uninstall. | dev.flutter.flutter_startup_stress |
--activity |
Activity name to launch. | .MainActivity |
--android-sdk |
Path to Android SDK or platform-tools. |
$ANDROID_HOME or $HOME/Android/Sdk |
To inspect the rendered UI on the device after the startup trace and screenshot have been saved, pass -w (or --wait-for-quit). The tool will block until you press 'q' (ignoring any other keys) before force-stopping and uninstalling the app:
dart run tools/bin/tools.dart install
dart run tools/bin/tools.dart run -w manual_checkBecause run uninstalls the app after each trace, re-run install before each iteration so every run starts from an identical first-launch state (including fresh SQLite DB creation and SharedPreferences initialization):
dart run tools/bin/tools.dart build \
--flutter-bin=/path/to/flutter/bin/flutter \
--local-engine-src-path=/path/to/flutter/engine/src
for i in 1 2 3; do
dart run tools/bin/tools.dart install
dart run tools/bin/tools.dart run "candidate_run${i}"
doneIn profile builds, the Impeller rendering backend is configured in android/app/src/main/AndroidManifest.xml:
- Vulkan:
<meta-data android:name="io.flutter.embedding.android.ImpellerBackend" android:value="vulkan" /> <meta-data android:name="io.flutter.embedding.android.EnableVulkanGPUTracing" android:value="true" />
- OpenGL ES:
<meta-data android:name="io.flutter.embedding.android.ImpellerBackend" android:value="opengles" /> <meta-data android:name="io.flutter.embedding.android.EnableOpenGLGPUTracing" android:value="true" />
Re-run dart run tools/bin/tools.dart build after changing AndroidManifest.xml.