mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-23 13:13:06 +00:00
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:
54
src/hpa.c
54
src/hpa.c
@@ -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++;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user