跪拜 Guibai
← All articles
Android · Flutter

Flutter Fixes CPU Affinity Bug That Cost Raster 20% on Snapdragon 8 Elite

By 恋猫de小郭 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

The merged fix removes a 16–21% median frame-time penalty for Flutter apps on Snapdragon 8 Elite-class hardware, where the Raster thread was confined to two big cores that rarely reached boost frequency. It's also a concrete case that contradicts manual core pinning as a performance tool, matching Android's advice to rely on ADPF instead.

Summary

Flutter's engine has long used a CPU affinity heuristic: it reads each core's max frequency from sysfs, labels the lowest-frequency group as efficiency cores, and keeps UI/Raster threads off them. On Snapdragon 8 Elite-class chips, which have two Prime cores and six Oryon performance cores but no little cores, this heuristic mislabels the six Oryon cores as efficiency, leaving Raster to run only on CPU 6–7 (the 4.61 GHz primes). A developer test on SM8850 showed that relaxing that affinity via sched_setaffinity cut Raster's median frame time by 16–21% and cumulative CPU time by 16–18%.

Perfetto traces explain the anomaly: the Raster thread is bursty—work per frame, then idle. On the two big cores it often starts at 883 MHz and spends 97–100% of its CPU time below 1 GHz, because the frequency never ramps before the frame's work ends. Allowed on all eight cores, the thread runs mainly on the six Oryon cores at an average 1.25–1.4 GHz, which is faster in practice.

The merged fix adds a HasNoLittleCores() check that reads /sys/devices/system/cpu/cpuN/cpu_capacity and compares min to max capacity. If the weakest core is at least 50% of the strongest (SM8850: 762 vs 1024), it concludes there are no little cores and expands UI/Raster affinity to all cores. Conservative fallbacks keep the old frequency-based grouping when capacity data is missing or uniform.

Takeaways
— PR #195071 merged into Flutter adds a HasNoLittleCores() check that reads cpu_capacity per core.
— On SM8850, the six Oryon cores have a capacity of 762 and the two Prime cores 1024, a 74.4% ratio, so the chip is classified as having no little cores.
— Before the fix, Raster was limited to CPU 6–7; its median frame time dropped 16–21% and CPU time 16–18% when affinity was relaxed to all cores.
— Perfetto showed the Raster thread on the two big cores spent 97–100% of CPU time below 1 GHz, starting at 883 MHz; on all cores it averaged 1.25–1.4 GHz.
— The fix's fallback: if any core lacks capacity data or all capacities are equal, Flutter keeps the old frequency-based grouping.
— The PR measured three scenarios; the median frame times dropped from 1.48 to 1.24 ms, 1.25 to 1.00 ms, and 1.74 to 1.38 ms.
Conclusions

A core's advertised max frequency is a poor proxy for bursty-thread performance: the two 4.61 GHz primes never exited the 883 MHz idle state before Raster's per-frame work finished, so the 'slower' six cores actually delivered the work faster on average.

The fix is a heuristic layered on a heuristic: capacity ratios identify 'no little cores' for this generation, but Flutter still avoids Android's recommended ADPF path, which remains a draft PR. The continued reliance on static affinity is a debt that will likely resurface on next-gen SoCs.

The test method itself is a useful debugging trick: changing thread affinity at the app level and measuring the delta with Perfetto cleanly separates scheduler behavior from application code, which is why the 16–21% regression was caught so precisely.

Concepts & terms
cpu_capacity
A per-CPU value in /sys/devices/system/cpu/cpuN/cpu_capacity that reports the relative compute capacity at the highest frequency, normalized such that the fastest core gets 1024. Used in this PR to detect whether a SoC really has little cores.
ADPF (Android Dynamic Performance Framework) / Performance Hint API
An Android API that lets threads hint about their workload (e.g., target frame duration) so the system can adjust core selection and clock frequency dynamically. Android recommends it over manual CPU affinity binding; Flutter has a draft PR to adopt it on Android 15+.
From the discussion
Featured comments
栈与烟火

Reverted again.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗