Fix hpa_strict_min_purge_interval option logic

We update `shard->last_purge` on each call of `hpa_try_purge` if we
purged something. This means, when `hpa_strict_min_purge_interval`
option is set only one slab will be purged, because on the next
call condition for too frequent purge protection
`since_last_purge_ms < shard->opts.min_purge_interval_ms` will always
be true. This is not an intended behaviour.

Instead, we need to check `min_purge_interval_ms` once and purge as many
pages as needed to satisfy requirements for `hpa_dirty_mult` option.

Make possible to count number of actions performed in unit tests (purge,
hugify, dehugify) instead of binary: called/not called. Extended current
unit tests with cases where we need to purge more than one page for a
purge phase.
This commit is contained in:
Dmitry Ilvokhin
2024-08-06 08:37:04 -07:00
committed by Qi Wang
parent 0a9f51d0d8
commit 143f458188
2 changed files with 209 additions and 42 deletions

View File

@@ -378,18 +378,6 @@ static bool
hpa_try_purge(tsdn_t *tsdn, hpa_shard_t *shard) {
malloc_mutex_assert_owner(tsdn, &shard->mtx);
/*
* Make sure we respect purge interval setting and don't purge
* too frequently.
*/
if (shard->opts.strict_min_purge_interval) {
uint64_t since_last_purge_ms = shard->central->hooks.ms_since(
&shard->last_purge);
if (since_last_purge_ms < shard->opts.min_purge_interval_ms) {
return false;
}
}
hpdata_t *to_purge = psset_pick_purge(&shard->psset);
if (to_purge == NULL) {
return false;
@@ -521,6 +509,19 @@ hpa_try_hugify(tsdn_t *tsdn, hpa_shard_t *shard) {
return true;
}
static bool
hpa_min_purge_interval_passed(tsdn_t *tsdn, hpa_shard_t *shard) {
malloc_mutex_assert_owner(tsdn, &shard->mtx);
if (shard->opts.strict_min_purge_interval) {
uint64_t since_last_purge_ms = shard->central->hooks.ms_since(
&shard->last_purge);
if (since_last_purge_ms < shard->opts.min_purge_interval_ms) {
return false;
}
}
return true;
}
/*
* Execution of deferred work is forced if it's triggered by an explicit
* hpa_shard_do_deferred_work() call.
@@ -545,18 +546,25 @@ hpa_shard_maybe_do_deferred_work(tsdn_t *tsdn, hpa_shard_t *shard,
* Always purge before hugifying, to make sure we get some
* ability to hit our quiescence targets.
*/
while (hpa_should_purge(tsdn, shard) && nops < max_ops) {
if (!hpa_try_purge(tsdn, shard)) {
/*
* It is fine if we couldn't purge as sometimes
* we try to purge just to unblock
* hugification, but there is maybe no dirty
* pages at all at the moment.
*/
break;
/*
* Make sure we respect purge interval setting and don't purge
* too frequently.
*/
if (hpa_min_purge_interval_passed(tsdn, shard)) {
while (hpa_should_purge(tsdn, shard) && nops < max_ops) {
if (!hpa_try_purge(tsdn, shard)) {
/*
* It is fine if we couldn't purge as sometimes
* we try to purge just to unblock
* hugification, but there is maybe no dirty
* pages at all at the moment.
*/
break;
}
malloc_mutex_assert_owner(tsdn, &shard->mtx);
nops++;
}
malloc_mutex_assert_owner(tsdn, &shard->mtx);
nops++;
}
/*