The Catan team looks at data (traces, stack samples, histograms…) on a regular basis to understand Chrome performance. As part of that work, we found that net::TCPSocketWin’s usage of base::ObjectWatcher, to be notified of completed read/writes, was among the top sources of context switches in local browsing sessions (bug). We took special interest in this because:
We have a long time suspicion, based on system traces analysis, that heavy context switching negatively affects Chrome performance.
Context switches induced by net::TCPSocketWin’s usage of base::ObjectWatcher can be avoided by using I/O Completion ports instead of events to be notified of completed read/writes.
The context switches of interest occur:
When an event is signaled, a thread controlled by Windows posts to the IO thread [code].
The IO thread then unregisters the wait, which often involves being descheduled [code].
We would like to study the effect of eliminating the context switches induced by net::TCPSocketWin’s usage of base::ObjectWatcher on Chrome’s top level metrics (LCP, INP) and low level metrics (Net.HttpTimeToFirstByte, Net.HttpJob.TotalTimeSuccess) via a field experiment. If the effect is positive, we can consider shipping the change to make Chrome faster. For my team, it would also mean that investing further in eliminating context switches is worth it. To conduct this experiment, we implemented an alternative version of net::TCPSocketWin which uses I/O completion ports instead of events to be notified of completed read/writes:
Pre-work to facilitate adding a new implementation:
5725524: Make SocketDataPump work when TCPSocket::ReadIfReady isn't implemented.
5627341: [net] Refactor TCPSocketWin to allow alternative read/write impls.
Implementation:
5627052: [net] Add TCPSocketWin implementation based on IO completion port.
5796670: [net] Handle synchronous write completion in TcpSocketIoCompletionPortWin.
Testing config: