mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-23 21:23:06 +00:00
HPA: Generalize purging.
Previously, we would purge a hugepage only when it's completely empty. With this change, we can purge even when only partially empty. Although the heuristic here is still fairly primitive, this infrastructure can scale to become more advanced.
This commit is contained in:
committed by
David Goldblatt
parent
70692cfb13
commit
30b9e8162b
35
src/hpdata.c
35
src/hpdata.c
@@ -24,6 +24,7 @@ hpdata_init(hpdata_t *hpdata, void *addr, uint64_t age) {
|
||||
hpdata->h_huge = false;
|
||||
hpdata->h_mid_purge = false;
|
||||
hpdata->h_mid_hugify = false;
|
||||
hpdata->h_in_psset = false;
|
||||
hpdata_longest_free_range_set(hpdata, HUGEPAGE_PAGES);
|
||||
hpdata->h_nactive = 0;
|
||||
fb_init(hpdata->active_pages, HUGEPAGE_PAGES);
|
||||
@@ -36,6 +37,7 @@ hpdata_init(hpdata_t *hpdata, void *addr, uint64_t age) {
|
||||
void *
|
||||
hpdata_reserve_alloc(hpdata_t *hpdata, size_t sz) {
|
||||
hpdata_assert_consistent(hpdata);
|
||||
assert(!hpdata_in_psset_get(hpdata));
|
||||
assert((sz & PAGE_MASK) == 0);
|
||||
size_t npages = sz >> LG_PAGE;
|
||||
assert(npages <= hpdata_longest_free_range_get(hpdata));
|
||||
@@ -116,6 +118,7 @@ hpdata_reserve_alloc(hpdata_t *hpdata, size_t sz) {
|
||||
void
|
||||
hpdata_unreserve(hpdata_t *hpdata, void *addr, size_t sz) {
|
||||
hpdata_assert_consistent(hpdata);
|
||||
assert(!hpdata->h_in_psset);
|
||||
assert(((uintptr_t)addr & PAGE_MASK) == 0);
|
||||
assert((sz & PAGE_MASK) == 0);
|
||||
size_t begin = ((uintptr_t)addr - (uintptr_t)hpdata_addr_get(hpdata))
|
||||
@@ -144,6 +147,7 @@ hpdata_unreserve(hpdata_t *hpdata, void *addr, size_t sz) {
|
||||
void
|
||||
hpdata_purge_begin(hpdata_t *hpdata, hpdata_purge_state_t *purge_state) {
|
||||
hpdata_assert_consistent(hpdata);
|
||||
assert(!hpdata->h_in_psset);
|
||||
assert(!hpdata->h_mid_purge);
|
||||
assert(!hpdata->h_mid_hugify);
|
||||
hpdata->h_mid_purge = true;
|
||||
@@ -181,6 +185,7 @@ hpdata_purge_next(hpdata_t *hpdata, hpdata_purge_state_t *purge_state,
|
||||
* a consistent state.
|
||||
*/
|
||||
assert(hpdata->h_mid_purge);
|
||||
assert(!hpdata->h_in_psset);
|
||||
/* Should have dehugified already (if necessary). */
|
||||
assert(!hpdata->h_huge);
|
||||
assert(!hpdata->h_mid_hugify);
|
||||
@@ -210,6 +215,7 @@ hpdata_purge_next(hpdata_t *hpdata, hpdata_purge_state_t *purge_state,
|
||||
void
|
||||
hpdata_purge_end(hpdata_t *hpdata, hpdata_purge_state_t *purge_state) {
|
||||
hpdata_assert_consistent(hpdata);
|
||||
assert(!hpdata->h_in_psset);
|
||||
assert(hpdata->h_mid_purge);
|
||||
assert(!hpdata->h_mid_hugify);
|
||||
hpdata->h_mid_purge = false;
|
||||
@@ -230,6 +236,7 @@ hpdata_purge_end(hpdata_t *hpdata, hpdata_purge_state_t *purge_state) {
|
||||
void
|
||||
hpdata_hugify_begin(hpdata_t *hpdata) {
|
||||
hpdata_assert_consistent(hpdata);
|
||||
assert(!hpdata_in_psset_get(hpdata));
|
||||
assert(!hpdata->h_mid_purge);
|
||||
assert(!hpdata->h_mid_hugify);
|
||||
hpdata->h_mid_hugify = true;
|
||||
@@ -242,6 +249,11 @@ hpdata_hugify_begin(hpdata_t *hpdata) {
|
||||
void
|
||||
hpdata_hugify_end(hpdata_t *hpdata) {
|
||||
hpdata_assert_consistent(hpdata);
|
||||
/*
|
||||
* This is the exception to the "no metadata tweaks while in the psset"
|
||||
* rule.
|
||||
*/
|
||||
/* assert(!hpdata_in_psset_get(hpdata)); */
|
||||
assert(!hpdata->h_mid_purge);
|
||||
assert(hpdata->h_mid_hugify);
|
||||
hpdata->h_mid_hugify = false;
|
||||
@@ -251,30 +263,9 @@ hpdata_hugify_end(hpdata_t *hpdata) {
|
||||
void
|
||||
hpdata_dehugify(hpdata_t *hpdata) {
|
||||
hpdata_assert_consistent(hpdata);
|
||||
/*
|
||||
* These asserts are morally right; for now, though, we have the "purge a
|
||||
* hugepage only in its entirety, when it becomes empty", path sharing
|
||||
* hpdata_dehugify with the new purge pathway coming in the next
|
||||
* commit.
|
||||
*/
|
||||
/*
|
||||
assert(!hpdata_in_psset_get(hpdata));
|
||||
assert(hpdata->h_mid_purge);
|
||||
assert(!hpdata->h_mid_hugify);
|
||||
*/
|
||||
hpdata->h_huge = false;
|
||||
hpdata_assert_consistent(hpdata);
|
||||
}
|
||||
|
||||
void
|
||||
hpdata_purge(hpdata_t *hpdata) {
|
||||
hpdata_assert_consistent(hpdata);
|
||||
/*
|
||||
* The hpdata must be empty; we don't (yet) support partial purges of
|
||||
* hugepages.
|
||||
*/
|
||||
assert(hpdata->h_nactive == 0);
|
||||
fb_unset_range(hpdata->dirty_pages, HUGEPAGE_PAGES, 0, HUGEPAGE_PAGES);
|
||||
fb_init(hpdata->dirty_pages, HUGEPAGE_PAGES);
|
||||
hpdata->h_ndirty = 0;
|
||||
hpdata_assert_consistent(hpdata);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user