Skip to content

Commit 83fa8ec

Browse files
authored
MallocMS page accounting (#689)
This PR changes how our malloc mark sweep accounts for memory. We are currently accounting bytes used, which is wrong. This PR changes that to page-based accounting. This PR addresses the issue #649 for malloc mark sweep (further work is still needed for the issue for our malloc API). * by default, we do not use bulk XOR for malloc mark sweep (which is known to have issues with page accounting) * Allow different malloc page size for library malloc
1 parent 30771e1 commit 83fa8ec

File tree

7 files changed

+211
-102
lines changed

7 files changed

+211
-102
lines changed

.github/scripts/ci-doc.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ if ! cat $project_root/src/plan/mod.rs | grep -q "pub mod mygc;"; then
2020
fi
2121
cargo build
2222

23-
cargo install mdbook
23+
# Install mdbook using the stable toolchain (mdbook uses scoped-tls which requires rust 1.59.0)
24+
cargo +stable install mdbook
2425
mdbook build $project_root/docs/portingguide
2526
mdbook build $project_root/docs/tutorial

.github/workflows/api-check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ jobs:
2828
- name: Install cargo-public-api
2929
run: cargo install cargo-public-api
3030
- name: API Diff
31-
run: cargo public-api --diff-git-checkouts ${GITHUB_BASE_REF} ${{ github.event.pull_request.head.sha }} --deny=all
31+
run: cargo public-api --diff-git-checkouts origin/${GITHUB_BASE_REF} ${{ github.event.pull_request.head.sha }} --deny=all

src/policy/mallocspace/global.rs

Lines changed: 181 additions & 98 deletions
Large diffs are not rendered by default.

src/policy/mallocspace/metadata.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pub(crate) const ACTIVE_CHUNK_METADATA_SPEC: SideMetadataSpec =
4848
// XXX: This metadata spec is currently unused as we need to add a performant way to calculate
4949
// how many pages are active in this metadata spec. Explore SIMD vectorization with 8-bit integers
5050
pub(crate) const ACTIVE_PAGE_METADATA_SPEC: SideMetadataSpec =
51-
crate::util::metadata::side_metadata::spec_defs::MS_ACTIVE_PAGE;
51+
crate::util::metadata::side_metadata::spec_defs::MALLOC_MS_ACTIVE_PAGE;
5252

5353
pub(crate) const OFFSET_MALLOC_METADATA_SPEC: SideMetadataSpec =
5454
crate::util::metadata::side_metadata::spec_defs::MS_OFFSET_MALLOC;
@@ -173,6 +173,15 @@ pub unsafe fn is_marked_unsafe<VM: VMBinding>(object: ObjectReference) -> bool {
173173
VM::VMObjectModel::LOCAL_MARK_BIT_SPEC.load::<VM, u8>(object, None) == 1
174174
}
175175

176+
/// Set the page mark from 0 to 1. Return true if we set it successfully in this call.
177+
pub(super) fn compare_exchange_set_page_mark(page_addr: Address) -> bool {
178+
// The spec has 1 byte per each page. So it won't be the case that other threads may race and access other bits for the spec.
179+
// If the compare-exchange fails, we know the byte was set to 1 before this call.
180+
ACTIVE_PAGE_METADATA_SPEC
181+
.compare_exchange_atomic::<u8>(page_addr, 0, 1, Ordering::SeqCst, Ordering::SeqCst)
182+
.is_ok()
183+
}
184+
176185
#[allow(unused)]
177186
pub(super) fn is_page_marked(page_addr: Address) -> bool {
178187
ACTIVE_PAGE_METADATA_SPEC.load_atomic::<u8>(page_addr, Ordering::SeqCst) == 1
@@ -217,6 +226,7 @@ pub fn unset_alloc_bit(object: ObjectReference) {
217226
alloc_bit::unset_alloc_bit(object);
218227
}
219228

229+
#[allow(unused)]
220230
pub(super) fn set_page_mark(page_addr: Address) {
221231
ACTIVE_PAGE_METADATA_SPEC.store_atomic::<u8>(page_addr, 1, Ordering::SeqCst);
222232
}
@@ -246,6 +256,7 @@ pub unsafe fn unset_mark_bit<VM: VMBinding>(object: ObjectReference) {
246256
VM::VMObjectModel::LOCAL_MARK_BIT_SPEC.store::<VM, u8>(object, 0, None);
247257
}
248258

259+
#[allow(unused)]
249260
pub(super) unsafe fn unset_page_mark_unsafe(page_addr: Address) {
250261
ACTIVE_PAGE_METADATA_SPEC.store::<u8>(page_addr, 0)
251262
}

src/util/alloc/allocator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ pub trait Allocator<VM: VMBinding>: Downcast {
250250
_allocation_bytes,
251251
*plan.options.analysis_factor
252252
);
253+
253254
plan.analysis_manager.alloc_hook(size, align, offset);
254255
}
255256
}

src/util/malloc/library.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,19 @@ pub use self::libc_malloc::*;
1313
#[cfg(feature = "malloc_mimalloc")]
1414
pub use self::mimalloc::*;
1515

16+
/// When we count page usage of library malloc, we assume they allocate in pages. For some malloc implementations,
17+
/// they may use a larger page (e.g. mimalloc's 64K page). For libraries that we are not sure, we assume they use
18+
/// normal 4k pages.
19+
pub const BYTES_IN_MALLOC_PAGE: usize = 1 << LOG_BYTES_IN_MALLOC_PAGE;
20+
1621
// Different malloc libraries
1722

1823
// TODO: We should conditinally include some methods in the module, such as posix extension and GNU extension.
1924

2025
#[cfg(feature = "malloc_jemalloc")]
2126
mod jemalloc {
27+
// Normal 4K page
28+
pub const LOG_BYTES_IN_MALLOC_PAGE: u8 = crate::util::constants::LOG_BYTES_IN_PAGE;
2229
// ANSI C
2330
pub use jemalloc_sys::{calloc, free, malloc, realloc};
2431
// Posix
@@ -29,6 +36,8 @@ mod jemalloc {
2936

3037
#[cfg(feature = "malloc_mimalloc")]
3138
mod mimalloc {
39+
// MiMalloc 64K Page
40+
pub const LOG_BYTES_IN_MALLOC_PAGE: u8 = 16;
3241
// ANSI C
3342
pub use mimalloc_sys::{
3443
mi_calloc as calloc, mi_free as free, mi_malloc as malloc, mi_realloc as realloc,
@@ -41,6 +50,8 @@ mod mimalloc {
4150

4251
#[cfg(feature = "malloc_hoard")]
4352
mod hoard {
53+
// Normal 4K page
54+
pub const LOG_BYTES_IN_MALLOC_PAGE: u8 = crate::util::constants::LOG_BYTES_IN_PAGE;
4455
// ANSI C
4556
pub use hoard_sys::{calloc, free, malloc, realloc};
4657
// Posix
@@ -56,6 +67,8 @@ mod hoard {
5667
feature = "malloc_hoard",
5768
)))]
5869
mod libc_malloc {
70+
// Normal 4K page
71+
pub const LOG_BYTES_IN_MALLOC_PAGE: u8 = crate::util::constants::LOG_BYTES_IN_PAGE;
5972
// ANSI C
6073
pub use libc::{calloc, free, malloc, realloc};
6174
// Posix

src/util/metadata/side_metadata/spec_defs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ define_side_metadata_specs!(
6666
define_side_metadata_specs!(
6767
last_spec_as LAST_LOCAL_SIDE_METADATA_SPEC,
6868
// Mark pages by (malloc) marksweep
69-
MS_ACTIVE_PAGE = (global: false, log_num_of_bits: 3, log_bytes_in_region: LOG_BYTES_IN_PAGE as usize),
69+
MALLOC_MS_ACTIVE_PAGE = (global: false, log_num_of_bits: 3, log_bytes_in_region: crate::util::malloc::library::LOG_BYTES_IN_MALLOC_PAGE as usize),
7070
// Record objects allocated with some offset
7171
MS_OFFSET_MALLOC = (global: false, log_num_of_bits: 0, log_bytes_in_region: LOG_MIN_OBJECT_SIZE as usize),
7272
// Mark lines by immix

0 commit comments

Comments
 (0)