Too much CPU usage spent in the native event loop when it is woken up by another thread
Categories
(Core :: Widget: Cocoa, defect, P3)
Tracking
()
People
(Reporter: mstange, Unassigned)
References
Details
(Keywords: power)
Profile: https://share.firefox.dev/2YFEghw
Our native event loop on macOS seems to have a lot of overhead. This causes unnecessary CPU usage if other threads post events to the main thread of the parent process (which is something that happens all the time).
Steps to reproduce:
- Open the browser console. (Not the web console! We want to execute JS in the parent process. Set
devtools.chrome.enabled
totrue
if you need to.) - Paste the following into the console's text field and press enter:
let eventChurner = (function () {
let messageName = 'ping-pong';
let workerJs = `
onmessage = e => {
postMessage(e.data);
};
`;
let blobUrl = URL.createObjectURL(new Blob([workerJs]));
let worker = new Worker(blobUrl);
function handleMessage(event) {
worker.postMessage(event.data);
}
return {
start: () => {
worker.addEventListener('message', handleMessage);
worker.postMessage('ping-pong');
},
stop: () => {
worker.removeEventListener('message', handleMessage);
worker.terminate();
},
};
})();
- Execute
eventChurner.start()
. - Start your profiler, wait for a bit, and capture the profile.
- Important: execute
eventChurner.stop()
. (otherwise you'll keep burning CPU)
Expected results:
Most of the time should be spent either idle or running the Gecko Worker runnable
.
Actual results:
https://share.firefox.dev/2YFEghw
0% idle, ~7% Worker runnable
, 93% event loop overhead.
Comment 1•4 years ago
|
||
I wouldn't be very surprised if we have similar issues in parent process also in other platforms.
AppShell code hasn't been optimized.... ever?
Reporter | ||
Comment 2•4 years ago
|
||
The macOS AppShell code was last optimized 7 years ago, in bug 996848. (Filing this bug gave me a déjà vu of filing bug 606937...)
Updated•4 years ago
|
Comment 3•3 years ago
|
||
So it looks like just removing this call to postEvent might be sufficient to mostly fix the problem. I believe, the other call to postEvent is only used when we're nesting.
I've pushed to try to see how things look:
https://treeherder.mozilla.org/jobs?repo=try&revision=1162208aa7cdab03c0e29f843292fdf7addfbdaf
Comment 4•3 years ago
|
||
I reprofiled with bug 1690687 landed.
https://share.firefox.dev/2WWTj9D
It looks a lot better.
Reporter | ||
Comment 5•3 years ago
|
||
Much better!
My profile from comment 0 has ~4800 message events per second. Your profile from comment 4 has ~14000 message events per second. So about a 3x throughput increase.
(I executed the following on the web console:)
function avgRate(markers) {
const firstStart = markers[0].start;
const lastStart = markers[markers.length - 1].start;
const duration = lastStart - firstStart;
const markersPerMs = (markers.length - 1) / duration;
return markersPerMs * 1000;
}
avgRate(filteredMarkers.filter(m => m.name === "DOMEvent"))
Comment 6•2 years ago
|
||
Markus, given your comment I'm lowering the severity, but perhaps this bug can be outright closed?
Reporter | ||
Comment 7•2 years ago
|
||
Sounds good.
Description
•