We can defer the purging of arenas to happen during idle processing on the main thread.
We already have the following prerequisites thanks to bug 1488780:
- The (often) expensive OS functions to give back memory pages are not blocking the use of the arena on other threads anymore.
- A single call to moz_may_purge_one_now (D232083) wraps just arena_t::Purge() that will just do "some work on one chunk" and tell if more is needed, giving us a fine grained control.
Synchronous purging can block the caller of a memory freeing function for an unexpectedly long time. Furthermore, memory that might be reclaimed very soon can be madvised early and thus its reuse can lead to frequent page faults.
We thus use moz_enable_deferred_purge (see D232083) to queue purge requests and execute them on the main thread only if it is about to become idle. We do this using an IdleTaskRunner that ensures we won't purge too often or never.
We believe that the main thread being idle is probably the best easy indicator we have to tell if the process is idle enough to purge without performance regrets.
We expect the peak memory usage of a single arena to not be affected significantly by this during normal use, but the time that this peak holds up might extend. This means the peak sum of all memory from all running processes may rise for short periods of time until enough purges happened on potentially several processes.
There is a chance to mitigate this effect by lowering the settings of allowed dirty pages for arenas, as there should be less churn in general with this patch, potentially resulting in a lower memory usage in average.
Differential Revision: https://phabricator.services.mozilla.com/D220616