-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Even on simple apps on Android (like the inappropriately named complex_layout), we seem to occassionally drop frames on the UI thread every so often (Impeller or Skia).
At first I thought it might be a GC or something like that, but looking at perfetto traces I can see that some times the UI thread ends up running on the slow cores of the Pixel 6 Pro 2.80 GHz -> 1.80 GHz . For the scrolling apps that seems to be OK sometimes, unless perhaps some new item needs to be laid out and rendered and then we end up dropping the frame.
Perfetto Trace
Release Mode Performance Overlay
The Pixel 6 Pro that I'm using, and many other Android devices use the Arm Big.LITTLE CPU architecture: About half of the cores are "efficiency" cores and are significantly slower ~50% than the other half of the "performance" cores. While the Flutter engine does set priorities of its worker threads to appropriate levels, this does not seem sufficient to ensure that UI/raster workloads are only run on the performance cores.
Furhtermore, the engine uses the concurrency level in many places (IO/Raster worker count) where it would be more appropriate to use the number of fast/slow cores - or about half the concurrency level. This may ultimately be the cause of issues like #132690 and #129392 , but this needs more investigation.
CPU/Thread Affinity Masking
We can force the UI/Raster threads to only run on certain CPUs via
in android_shell_holder.cc
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(6, &set);
CPU_SET(7, &set);
if (sched_setaffinity(gettid(), sizeof(set), &set) != 0) {
FML_LOG(ERROR) << "Failed to set affinity";
}This takes advantage of the fact that I can 1) get the CPU count from sched_getaffinity and 2) am making an assumption that the large CPU indexes are the faster cores. The result of making this change to both Raster/UI threads is that the max UI thread time reported on complex_layout app is about 1/3rd what it used to be:

