Symmetrize deferred-work execution by moving it from arena to PAC

This commit is contained in:
guangli-dai 2026-06-28 14:43:04 -07:00 committed by Guangli Dai
parent b44e84086f
commit 7f52ac7af3
5 changed files with 168 additions and 76 deletions

View file

@ -111,12 +111,6 @@ struct pa_shard_s {
pac_t pac;
};
static inline bool
pa_shard_dont_decay_muzzy(pa_shard_t *shard) {
return ecache_npages_get(&shard->pac.ecache_muzzy) == 0
&& pac_decay_ms_get(&shard->pac, extent_state_muzzy) <= 0;
}
static inline ehooks_t *
pa_shard_ehooks_get(const pa_shard_t *shard) {
return base_ehooks_get(shard->base);
@ -188,15 +182,14 @@ bool pa_decay_ms_set(tsdn_t *tsdn, pa_shard_t *shard, extent_state_t state,
ssize_t pa_decay_ms_get(pa_shard_t *shard, extent_state_t state);
/*
* Do deferred work on this PA shard.
*
* Morally, this should do both PAC decay and the HPA deferred work. For now,
* though, the arena, background thread, and PAC modules are tightly interwoven
* in a way that's tricky to extricate, so we only do the HPA-specific parts.
* Do deferred work on this PA shard: both PAC decay and the HPA deferred work
* symetrically. The only exception in the symetry is PAC decay-purge policy
* requires the eagerness, which is passed in from the arena.
*/
void pa_shard_set_deferral_allowed(
tsdn_t *tsdn, pa_shard_t *shard, bool deferral_allowed);
void pa_shard_do_deferred_work(tsdn_t *tsdn, pa_shard_t *shard);
void pa_shard_do_deferred_work(
tsdn_t *tsdn, pa_shard_t *shard, pac_purge_eagerness_t eagerness);
void pa_shard_try_deferred_work(tsdn_t *tsdn, pa_shard_t *shard);
uint64_t pa_shard_time_until_deferred_work(tsdn_t *tsdn, pa_shard_t *shard);

View file

@ -231,6 +231,32 @@ bool pac_maybe_decay_purge(tsdn_t *tsdn, pac_t *pac, decay_t *decay,
pac_decay_stats_t *decay_stats, ecache_t *ecache,
pac_purge_eagerness_t eagerness);
/*
* Result of a pac_do_deferred_work() pass. Reported per decay state so the
* caller (on the user-inline path) can decide, per state, whether to notify the
* background thread. npages_new is the per-state epoch backlog delta, only
* meaningful when the corresponding *_epoch_advanced is true.
*/
typedef struct pac_deferred_work_result_s pac_deferred_work_result_t;
struct pac_deferred_work_result_s {
size_t dirty_npages_new;
size_t muzzy_npages_new;
bool dirty_epoch_advanced;
bool muzzy_epoch_advanced;
};
/*
* Non-forced deferred decay work for both the dirty and muzzy states.
* Corresponding decay->mtx are acquired internally.
*/
void pac_do_deferred_work(tsdn_t *tsdn, pac_t *pac,
pac_purge_eagerness_t eagerness, pac_deferred_work_result_t *result);
/*
* Fully decay the extents of the given state, acquiring decay->mtx internally.
*/
void pac_decay_all_now(tsdn_t *tsdn, pac_t *pac, extent_state_t state);
/*
* Gets / sets the maximum amount that we'll grow an arena down the
* grow-retained pathways (unless forced to by an allocaction request).
@ -247,6 +273,13 @@ bool pac_decay_ms_set(tsdn_t *tsdn, pac_t *pac, extent_state_t state,
ssize_t decay_ms, pac_purge_eagerness_t eagerness);
ssize_t pac_decay_ms_get(pac_t *pac, extent_state_t state);
/* Whether the muzzy decay path is relevant (muzzy pages exist, or decay is on). */
static inline bool
pac_should_decay_muzzy(pac_t *pac) {
return ecache_npages_get(&pac->ecache_muzzy) != 0
|| pac_decay_ms_get(pac, extent_state_muzzy) > 0;
}
void pac_destroy(tsdn_t *tsdn, pac_t *pac);
void pac_sec_flush(tsdn_t *tsdn, pac_t *pac);