[base] Add a feature to busy loop in MessagePump on renderer main
The renderer main thread often sleeps for a very short duration,
frequently a few 100s of us, even though the message pump thinks that it
will sleep for longer than that (typically due to some other thread
posting a task to the main thread). Prior to this CL, this results in
the renderer main thread sleeping (on linux, using FUTEX_WAIT) and thus
relinquishing the CPU. This has a couple consequences:
- Wakeup latency, since another task may be running on the CPU
- Lower CPU core utilization, since kernel load tracking will see the
core as less utilized, and may ramp down the frequency, which can take
a long time to ramp back up.
Ideally, if we know that the next sleep is likely going to be very
short, a better approach from a latency perspective is thus to
busy-loop, waiting for the next task. This CL tries to approximate this,
by busy-looping, only on the renderer main thread. While we of course
cannot predict the future, the very simple heuristic here tries to take
some historical information into account, yet avoid busy-looping for
normal cases such as a regularly-scheduled BeginMainFrame (every 1/60th
or 1/120th of a second).
Locally, on a Pixel 9 Pro XL running Android 15, this improves the speedometer
3.0 score by around 10%. More specifically, median of three runs locally:
- Without: 15.4
- With: 16.9
There is of course a pretty obvious drawback: power usage, since this
may prevent the big core from lowering its frequency, or even entering a
sleep state. We have power usage metrics, and this is why this is added
as a feature, to assess the impact in the wild.
Change-Id: Id61c621f1deb9d6a613c8641af1cf4be5fdfb7ec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6088387
Reviewed-by: Eric Seckler <[email protected]>
Reviewed-by: Alexander Timin <[email protected]>
Commit-Queue: Benoit Lize <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1406421}
diff --git a/base/message_loop/message_pump_default.h b/base/message_loop/message_pump_default.h
index c8f7274..bf918d9b 100644
--- a/base/message_loop/message_pump_default.h
+++ b/base/message_loop/message_pump_default.h
@@ -29,12 +29,22 @@
void ScheduleDelayedWork(
const Delegate::NextWorkInfo& next_work_info) override;
+ // Visible for testing.
+ void RecordWaitTime(base::TimeDelta wait_time);
+ bool ShouldBusyLoop() const;
+
private:
+ // Returns whether the event was signaled.
+ bool BusyWaitOnEvent(base::TimeTicks before);
+
// This flag is set to false when Run should return.
bool keep_running_;
// Used to sleep until there is more work to do.
WaitableEvent event_;
+
+ base::TimeDelta last_wait_time_;
+ base::TimeDelta wait_time_exponential_moving_average_;
};
} // namespace base