Repository navigation
Description
Steps to reproduce
- Use a phone with one of these chips: SM8750 (8 Elite), SM8850 (8 Elite Gen 5) or SM8845 (8 Gen 5). They have two prime and six performance Oryon cores, and no little cores. I tested the SM8850 only.
flutter create affinity_repro, thenflutter run --profile.- List the cores and the CPUs that the engine's threads are allowed to run on:
adb shell 'for c in /sys/devices/system/cpu/cpu[0-9]*; do echo "${c##*/} capacity $(cat $c/cpu_capacity) max_freq $(cat $c/cpufreq/cpuinfo_max_freq)"; done'
adb shell 'for t in /proc/$(pidof dev.example.affinity_repro)/task/*; do echo "$(cat $t/comm): $(grep Cpus_allowed_list $t/status)"; done 2>/dev/null' | grep -E '\.(raster|io):'Expected results
The raster thread may also run on the six performance cores. None of them is a little core: the kernel rates them 762 of the prime cores' 1024 (cpu_capacity).
Actual results
On an SM8850 phone, the counter app built with master 8636361, profile mode, after a cold start:
cpu0 capacity 762 max_freq 3628800
cpu1 capacity 762 max_freq 3628800
cpu2 capacity 762 max_freq 3628800
cpu3 capacity 762 max_freq 3628800
cpu4 capacity 762 max_freq 3628800
cpu5 capacity 762 max_freq 3628800
cpu6 capacity 1024 max_freq 4608000
cpu7 capacity 1024 max_freq 4608000
1.raster: Cpus_allowed_list: 6-7
1.io: Cpus_allowed_list: 0-5
android_shell_holder.cc sets the raster thread to CpuAffinity::kNotEfficiency, and CPUSpeedTracker counts the CPUs with the lowest cpuinfo_max_freq as efficiency cores. This came from flutter-team-archive/engine#54616 (after #153690), to keep the UI and raster threads off little cores. A chip without little cores also has a slowest group: here it is the six performance cores, so the raster thread is left with the two prime cores.
Nothing else keeps the prime cluster busy, so raster frames start at its lowest frequency. In our app (Flutter 3.47.7, which has the same affinity code; profile mode, Impeller Vulkan, SM8850), we traced the same scripted scenes with Perfetto twice. In the first run the raster threads kept the engine's affinity. In the second, the app set them to cores 0-7 with sched_setaffinity at startup:
| Scene | Raster frame p50 | Frames over 12 ms | Total raster thread run time |
|---|---|---|---|
| Scroll and fling a grid | 1.25 → 1.00 ms | 1 → 1 | 4237 → 3540 ms (−16%) |
| Open and scroll a detail page | 1.48 → 1.24 ms | 7 → 2 | 9584 → 7848 ms (−18%) |
| Switch tabs | 1.74 → 1.38 ms | 2 → 2 | 10718 → 8884 ms (−17%) |
- Pinned, the raster thread spent 97–100% of its run time below 1 GHz, starting at 883 MHz.
- Freed, it ran on the performance cores, averaging 1.25–1.4 GHz. That matches the RenderThread of a native app on the same phone.
- The time the raster thread waited to run did not grow (0–1% of its time).
- Power was not measured.
Code sample
Code sample
The app from flutter create, unchanged. The affinity does not depend on app code.
Performance profiling on master channel
- The issue still persists on the master channel
Timeline Traces
Timeline Traces JSON
A DevTools timeline does not show which core a thread runs on or the CPU frequency. The numbers above come from Perfetto system traces with sched and power/cpu_frequency. I can share traces recorded with the counter app if they help.
Video demonstration
N/A. The difference is in raster times, not something a video shows.
What target platforms are you seeing this bug on?
Android
OS/Browser name and version | Device information
Android 17 (API 37), kernel 6.12. realme RMX5200, Snapdragon 8 Elite Gen 5 (SM8850): 6 × Oryon at 3.63 GHz (capacity 762) and 2 × Oryon at 4.61 GHz (capacity 1024).
Does the problem occur on emulator/simulator as well as on physical devices?
No
Is the problem only reproducible with Impeller?
No. The affinity is set in android_shell_holder.cc for every renderer. The numbers above are with Impeller Vulkan.
Logs
Logs
See the output above.
Flutter Doctor output
Doctor output
[✓] Flutter (Channel master, 3.50.0-0.1.pre, on Ubuntu 26.04.1 LTS 6.18.54.1-microsoft-standard-WSL2, locale C.UTF-8) [4.5s]
• Flutter version 3.50.0-0.1.pre on channel master at /root/flutter-upstream/sdk-master
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 8636361c95 (71 minutes ago), 2026-10-22 13:43:40 +0000
• Engine revision 8636361c95
• Dart version 3.15.0 (build 3.15.0-62.0.dev)
• DevTools version 2.61.0
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-record-use, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration, enable-riscv64, enable-hcpp
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [103ms]
• Android SDK at /opt/android-sdk
• Emulator version unknown
• Platform android-37.0, build-tools 36.0.0
• Java binary at: /usr/bin/java
This JDK was found in the system PATH.
To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
• Java version OpenJDK Runtime Environment (build 21.0.12.1+1-1-26.04.4-Ubuntu)
• All Android licenses accepted.
[✓] Chrome - develop for the web [47ms]
• Chrome at google-chrome
[✗] Linux toolchain - develop for Linux desktop [205ms]
• Ubuntu clang version 21.1.8 (6ubuntu1)
• cmake version 4.2.3
• ninja version 1.13.2
• pkg-config version 2.5.1
✗ GTK 3.0 development libraries are required for Linux development.
They are likely available from your distribution (e.g.: apt install libgtk-3-dev)
! Unable to access driver information using 'eglinfo'.
It is likely available from your distribution (e.g.: apt install mesa-utils)
[✓] Proxy Configuration [54ms]
• HTTP_PROXY is set
• NO_PROXY is localhost,127.0.0.1,::1
• NO_PROXY contains localhost
• NO_PROXY contains 127.0.0.1
• NO_PROXY contains ::1
[✓] Connected device (3 available) [514ms]
• RMX5200 (wireless) (mobile) • <device id> • android-arm64 • Android 17 (API 37)
• Linux (desktop) • linux • linux-x64 • Ubuntu 26.04.1 LTS 6.18.54.1-microsoft-standard-WSL2
• Chrome (web) • chrome • web-javascript • Google Chrome 156.0.8078.47
[✓] Network resources [1,603ms]
• All expected network resources are available.
! Doctor found issues in 1 category.
Activity
mbcorona commentedon Oct 22, 2026
Hi @Lopution, thanks for the numbers and the clear root cause.
Routing to team-engine to evaluate; noted PR #195071
gaaclarke commentedon Oct 26, 2026
Can you quantify how this is affecting you?
Lopution commentedon Oct 27, 2026
Thanks for taking a look. On the SM8850, the cost mostly shows up on heavy frames. The raster thread is pinned to the two prime cores, and nothing else really uses them, so each burst of raster work starts at that cluster's lowest frequency (883 MHz) and sits under 1 GHz 97–100% of the time.
Same Perfetto A/B runs as in the issue (our app, profile mode, Impeller Vulkan, 120 Hz display, 8.3 ms budget). Pinned → unpinned:
Raster frames over 8.3 ms: 2 → 1 (grid scroll and fling), 14 → 12 (detail page), 5 → 3 (tab switches).
Single heavy frames (content differs between runs, so indicative only): the detail-page Hero frame went from 17.0 / 34.7 ms to 9.6–11.6 ms; the first frame after cold start from 28.3 to 15.9 ms; switching to a ranking tab from 13.1 / 11.0 / 8.3 ms to none over 8 ms.
Median raster frame time is down 16–21%; total raster thread CPU time down 16–18%. p99 didn't move: the longest frames are dominated by the work itself (glyph atlas, image uploads), not frequency. Typical frames fit the budget either way. What changes is extra dropped frames on transitions and cold start.
Right now we work around this in the app by widening the raster thread's affinity with sched_setaffinity at startup. We'd like to drop that once the engine handles it. The 8 Elite, 8 Elite Gen 5 and 8 Gen 5 power most Snapdragon flagships of the past two years, so every Flutter app on them gets the same pinning. I haven't measured power.
[Android] Let the raster thread use every core of a chip without litt…
Revert: [Android] Let the raster thread use every core of a chip with…
[Android] Let the raster thread use every core of a chip without litt…
Revert: [Android] Let the raster thread use every core of a chip with…
github-actions commentedon Nov 13, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.