Flutter's CPU Affinity Rollercoaster: Raster Thread Fix Rolled Back After 2x Regression, ADPF RFC Puts OS in Charge
Static CPU affinity keeps trading one device's jank for another's benchmark regression, so Flutter's render-thread placement remains a moving target on modern Android chips. A scheduler-aware approach like ADPF already shows 36–44% raster-time improvements in prototypes, but the remaining light-load regressions mean the framework still has to balance benchmark health against real-world device diversity.
Flutter keeps running into the same wall: its UI/Raster threads are short and latency-sensitive, but static CPU affinity choices keep misfiring across device architectures. On Snapdragon 8 Elite, restricting the Raster thread to two Prime Cores (4.61 GHz) could be slower than using the six Performance Cores (3.63 GHz) because of thread wake-up costs and frequency ramp-up delays. When Flutter widened the core pool in PR #195071, real devices got faster, but the official `fading_child_animation_perf` benchmark regressed by 2x in `average_frame_rasterizer_time_millis`, forcing a rollback.
This is the fourth round of affinity fixes since 2023. Each fix solved one device class and broke another: first restricting to performance cores to avoid slow cores, then expanding to avoid core crowding on Pixel 8, then fixing misclassification on Oryon's no-little-core design, now rolling back after benchmark regressions. A new RFC (#45) proposes dropping static core selection entirely and using Android's ADPF (Adaptive Performance APIs) to tell the OS which threads matter, the frame deadline, and how long the previous frame took. Prototype benchmarks on Pixel 8 and Pixel 9 show raster averages improving 36–44% in complex-layout and tiles scrolling, though light-load scenes on Pixel 8 and Lenovo Tab regress and Hybrid Composition still has thread-merging quirks.
Static CPU affinity is a fragile heuristic: every Flutter fix addresses the scheduler behavior of one chip generation, only to misfire on another, because it ignores frequency ramping, cluster occupancy, and power policy.
The 2x official benchmark regression outweighed the real-world gains on Snapdragon 8 Elite, revealing that Flutter's tuning is paced by its own automated metrics rather than by device-pattern-driven analysis.
Delegating scheduling to Android via ADPF is a structural shift: instead of telling Flutter which cores are 'fast', the framework communicates frame deadlines and workload characteristics to a scheduler that already juggles power, thermal, and other threads, which is a more sustainable model even if the prototype still has edge cases.