From b580ab6eef982b05b5d189336dfb8fe8d3c53db3 Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Thu, 4 Apr 2024 03:49:55 +0000 Subject: [PATCH] Try to allow enough virtual memory for nursery with constrained virtual memory environment. --- src/plan/generational/global.rs | 9 +++- src/util/options.rs | 32 +++++++++++--- ...test_nursery_virtual_memory_constrained.rs | 42 +++++++++++++++++++ ..._nursery_virtual_memory_not_constrained.rs | 42 +++++++++++++++++++ src/vm/tests/mock_tests/mod.rs | 2 + 5 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 src/vm/tests/mock_tests/mock_test_nursery_virtual_memory_constrained.rs create mode 100644 src/vm/tests/mock_tests/mock_test_nursery_virtual_memory_not_constrained.rs diff --git a/src/plan/generational/global.rs b/src/plan/generational/global.rs index a764eed0b7..cf53459cd2 100644 --- a/src/plan/generational/global.rs +++ b/src/plan/generational/global.rs @@ -5,6 +5,7 @@ use crate::plan::Plan; use crate::policy::copyspace::CopySpace; use crate::policy::space::Space; use crate::scheduler::*; +use crate::util::constants::LOG_BYTES_IN_PAGE; use crate::util::copy::CopySemantics; use crate::util::heap::gc_trigger::SpaceStats; use crate::util::heap::VMRequest; @@ -39,6 +40,12 @@ pub struct CommonGenPlan { impl CommonGenPlan { pub fn new(mut args: CreateSpecificPlanArgs) -> Self { + let max_heap_bytes = args + .global_args + .gc_trigger + .policy + .get_max_heap_size_in_pages() + << LOG_BYTES_IN_PAGE; let nursery = CopySpace::new( args.get_space_args( "nursery", @@ -47,7 +54,7 @@ impl CommonGenPlan { args.global_args .options .nursery - .estimate_virtual_memory_in_bytes(), + .estimate_virtual_memory_in_bytes(max_heap_bytes), false, ), ), diff --git a/src/util/options.rs b/src/util/options.rs index 5471310125..a2479cc2b0 100644 --- a/src/util/options.rs +++ b/src/util/options.rs @@ -426,15 +426,37 @@ pub enum NurserySize { impl NurserySize { /// Estimate the virtual memory needed for the nursery space. This is used during space creation. - pub fn estimate_virtual_memory_in_bytes(&self) -> usize { + pub fn estimate_virtual_memory_in_bytes(&self, max_heap_size_bytes: usize) -> usize { let virtual_memory_bytes = match *self { NurserySize::Bounded { min: _, max } => max, // Just use the default max nursery size -- the nursery won't get larger than that. - NurserySize::ProportionalBounded { min: _, max: _ } => { - if !crate::util::heap::vm_layout::vm_layout().force_use_contiguous_spaces { - DEFAULT_MAX_NURSERY_32 + NurserySize::ProportionalBounded { min: _, max } => { + use crate::util::heap::vm_layout::vm_layout; + let max_nursery_size_bytes = (max_heap_size_bytes as f64 * max) as usize; + if vm_layout().force_use_contiguous_spaces { + // This is the normal 64 bits settings. We should not need to worry about virtual memory. + // So just return whatever is needed. + max_nursery_size_bytes } else { - DEFAULT_MAX_NURSERY + // We may not have enough virtual memory in a setting with constrained virtual memory. + if vm_layout().available_bytes() > max_heap_size_bytes + max_nursery_size_bytes + { + // This check is just an estimate to see if we may run out of virtual memory address. + // This only works if all the other spaces do not reserve virtual memory more than + // what they really use (e.g. they use `VMRequest::discontiguous`). Otherwise, we + // may still run out of virtual memory address. + // TODO: What we really want here is to satisfy other vm requests first, and to allow + // the nursery to use whatever is left. But this is not possible right now. + // Changes like https://github.com/mmtk/mmtk-core/pull/1004 would allow this. + max_nursery_size_bytes + } else { + warn!( + "We are running with constrained virtual memory, {:?} may not be satisfied with the heap size {}. \ + We only allow the nursery space to use {} bytes virtual memory.", + self, max_heap_size_bytes, DEFAULT_MAX_NURSERY_32, + ); + DEFAULT_MAX_NURSERY_32 + } } } NurserySize::Fixed(sz) => sz, diff --git a/src/vm/tests/mock_tests/mock_test_nursery_virtual_memory_constrained.rs b/src/vm/tests/mock_tests/mock_test_nursery_virtual_memory_constrained.rs new file mode 100644 index 0000000000..54350da1cf --- /dev/null +++ b/src/vm/tests/mock_tests/mock_test_nursery_virtual_memory_constrained.rs @@ -0,0 +1,42 @@ +// GITHUB-CI: MMTK_PLAN=GenImmix + +use super::mock_test_prelude::*; + +use crate::util::heap::layout::vm_layout::*; +use crate::util::options::*; + +#[test] +pub fn constrained() { + with_mockvm( + default_setup, + || { + // 4G heap with a 32 bits vm layout. + const MB: usize = 1024 * 1024; + let heap_size = 4096 * MB; + let fixture = MutatorFixture::create_with_builder(|builder| { + builder.set_vm_layout(VMLayout::new_32bit()); + builder + .options + .nursery + .set(NurserySize::ProportionalBounded { + min: 0.1f64, + max: 1.0f64, + }); + builder + .options + .gc_trigger + .set(GCTriggerSelector::FixedHeapSize(heap_size)); + }); + // Use the default 32MB virtual memory. + assert_eq!( + fixture + .mmtk() + .get_options() + .nursery + .estimate_virtual_memory_in_bytes(heap_size), + 32 * MB, + ); + }, + no_cleanup, + ) +} diff --git a/src/vm/tests/mock_tests/mock_test_nursery_virtual_memory_not_constrained.rs b/src/vm/tests/mock_tests/mock_test_nursery_virtual_memory_not_constrained.rs new file mode 100644 index 0000000000..d85d72c996 --- /dev/null +++ b/src/vm/tests/mock_tests/mock_test_nursery_virtual_memory_not_constrained.rs @@ -0,0 +1,42 @@ +// GITHUB-CI: MMTK_PLAN=GenImmix + +use super::mock_test_prelude::*; + +use crate::util::heap::layout::vm_layout::*; +use crate::util::options::*; + +#[test] +pub fn non_constrained() { + with_mockvm( + default_setup, + || { + // 100M heap with a 32 bits vm layout. + const MB: usize = 1024 * 1024; + let heap_size = 100 * MB; + let fixture = MutatorFixture::create_with_builder(|builder| { + builder.set_vm_layout(VMLayout::new_32bit()); + builder + .options + .nursery + .set(NurserySize::ProportionalBounded { + min: 0.1f64, + max: 1.0f64, + }); + builder + .options + .gc_trigger + .set(GCTriggerSelector::FixedHeapSize(heap_size)); + }); + // We should use 100M virtual memory for nursery. + assert_eq!( + fixture + .mmtk() + .get_options() + .nursery + .estimate_virtual_memory_in_bytes(heap_size), + heap_size + ); + }, + no_cleanup, + ) +} diff --git a/src/vm/tests/mock_tests/mod.rs b/src/vm/tests/mock_tests/mod.rs index 51a085cec8..e2b19af214 100644 --- a/src/vm/tests/mock_tests/mod.rs +++ b/src/vm/tests/mock_tests/mod.rs @@ -43,6 +43,8 @@ mod mock_test_malloc_ms; mod mock_test_mmtk_julia_pr_143; #[cfg(feature = "nogc_lock_free")] mod mock_test_nogc_lock_free; +mod mock_test_nursery_virtual_memory_constrained; +mod mock_test_nursery_virtual_memory_not_constrained; #[cfg(target_pointer_width = "64")] mod mock_test_vm_layout_compressed_pointer; mod mock_test_vm_layout_default;