Skip to content

Commit 9f9e3c6

Browse files
author
Javad Amiri
authored
Side metadata performance regression (#264)
* reduce WCR of metadata space for 32-bits * fix bzero and unmap for 32-bits policy-specific * add the side_gc_header feature
1 parent 6cac4ff commit 9f9e3c6

28 files changed

+1376
-829
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ nogc_no_zeroing = ["nogc_lock_free"]
6565
# Q: Why do we need this as a compile time flat? We can always set the number of GC threads through options.
6666
single_worker = []
6767

68+
# To support VMs that do not provide in-header GC byte
69+
side_gc_header = []
70+
6871
# Do not modify the following line - ci-common.sh matches it
6972
# -- Mutally exclusive features --
7073
# Only one feature from each group can be provided. Otherwise build will fail.

docs/tutorial/code/mygc_semispace/global.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::plan::mygc::mutator::create_mygc_mutator;
99
use crate::plan::mygc::mutator::ALLOCATOR_MAPPING;
1010
use crate::plan::AllocationSemantics;
1111
use crate::plan::Plan;
12+
use crate::plan::PlanConstraints;
1213
use crate::policy::copyspace::CopySpace; // Add
1314
use crate::policy::space::Space;
1415
use crate::scheduler::gc_work::*; // Add
@@ -22,10 +23,9 @@ use crate::util::heap::VMRequest;
2223
use crate::util::options::UnsafeOptionsWrapper;
2324
use crate::util::OpaquePointer;
2425
use crate::vm::VMBinding;
25-
use crate::plan::PlanConstraints;
26-
use std::sync::atomic::{AtomicBool, Ordering}; // Add
27-
use std::sync::Arc;
2826
use enum_map::EnumMap;
27+
use std::sync::atomic::{AtomicBool, Ordering}; // Add
28+
use std::sync::Arc;
2929
// Remove #[allow(unused_imports)].
3030
// Remove handle_user_collection_request.
3131
// ANCHOR_END: imports
@@ -37,10 +37,10 @@ pub const ALLOC_MyGC: AllocationSemantics = AllocationSemantics::Default; // Add
3737
// Modify
3838
// ANCHOR: plan_def
3939
pub struct MyGC<VM: VMBinding> {
40-
pub hi: AtomicBool,
40+
pub hi: AtomicBool,
4141
pub copyspace0: CopySpace<VM>,
4242
pub copyspace1: CopySpace<VM>,
43-
pub common: CommonPlan<VM>,
43+
pub common: CommonPlan<VM>,
4444
}
4545
// ANCHOR_END: plan_def
4646

@@ -78,7 +78,7 @@ impl<VM: VMBinding> Plan for MyGC<VM> {
7878
// Modify
7979
// ANCHOR: gc_init
8080
fn gc_init(
81-
&mut self,
81+
&mut self,
8282
heap_size: usize,
8383
vm_map: &'static VMMap,
8484
scheduler: &Arc<MMTkScheduler<VM>>,
@@ -91,13 +91,15 @@ impl<VM: VMBinding> Plan for MyGC<VM> {
9191

9292
// Modify
9393
// ANCHOR: schedule_collection
94-
fn schedule_collection(&'static self, scheduler:&MMTkScheduler<VM>) {
94+
fn schedule_collection(&'static self, scheduler: &MMTkScheduler<VM>) {
9595
self.base().set_collection_kind();
9696
self.base().set_gc_status(GcStatus::GcPrepare);
9797
scheduler.work_buckets[WorkBucketStage::Unconstrained]
9898
.add(StopMutators::<MyGCProcessEdges<VM>>::new());
99-
scheduler.work_buckets[WorkBucketStage::Prepare].add(Prepare::<Self, MyGCCopyContext<VM>>::new(self));
100-
scheduler.work_buckets[WorkBucketStage::Release].add(Release::<Self, MyGCCopyContext<VM>>::new(self));
99+
scheduler.work_buckets[WorkBucketStage::Prepare]
100+
.add(Prepare::<Self, MyGCCopyContext<VM>>::new(self));
101+
scheduler.work_buckets[WorkBucketStage::Release]
102+
.add(Release::<Self, MyGCCopyContext<VM>>::new(self));
101103
scheduler.set_finalizer(Some(EndOfGC));
102104
}
103105
// ANCHOR_END: schedule_collection
@@ -114,7 +116,7 @@ impl<VM: VMBinding> Plan for MyGC<VM> {
114116
self.hi
115117
.store(!self.hi.load(Ordering::SeqCst), Ordering::SeqCst);
116118
// Flips 'hi' to flip space definitions
117-
let hi = self.hi.load(Ordering::SeqCst);
119+
let hi = self.hi.load(Ordering::SeqCst);
118120
self.copyspace0.prepare(hi);
119121
self.copyspace1.prepare(!hi);
120122
}
@@ -134,7 +136,7 @@ impl<VM: VMBinding> Plan for MyGC<VM> {
134136
self.tospace().reserved_pages()
135137
}
136138
// ANCHOR_END: plan_get_collection_reserve
137-
139+
138140
// Modify
139141
// ANCHOR: plan_get_pages_used
140142
fn get_pages_used(&self) -> usize {
@@ -191,11 +193,11 @@ impl<VM: VMBinding> MyGC<VM> {
191193
mmapper,
192194
&mut heap,
193195
),
194-
common: CommonPlan::new(vm_map, mmapper, options, heap, &MYGC_CONSTRAINTS),
196+
common: CommonPlan::new(vm_map, mmapper, options, heap, &MYGC_CONSTRAINTS, &[]),
195197
}
196198
}
197199
// ANCHOR_END: plan_new
198-
200+
199201
// ANCHOR: plan_space_access
200202
pub fn tospace(&self) -> &CopySpace<VM> {
201203
if self.hi.load(Ordering::SeqCst) {

docs/tutorial/src/mygc/ss/exercise_solution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ In `global.rs`:
6565
mmapper,
6666
&mut heap,
6767
),
68-
common: CommonPlan::new(vm_map, mmapper, options, heap, &TRIPLESPACE_CONSTRAINTS),
68+
common: CommonPlan::new(vm_map, mmapper, options, heap, &TRIPLESPACE_CONSTRAINTS, &[]),
6969
}
7070
}
7171
```

src/plan/gencopy/global.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use super::{
33
gc_work::{GenCopyCopyContext, GenCopyMatureProcessEdges, GenCopyNurseryProcessEdges},
44
LOGGING_META,
55
};
6-
use crate::plan::global::BasePlan;
76
use crate::plan::global::CommonPlan;
87
use crate::plan::global::GcStatus;
98
use crate::plan::AllocationSemantics;
@@ -23,11 +22,10 @@ use crate::util::heap::VMRequest;
2322
use crate::util::options::UnsafeOptionsWrapper;
2423
#[cfg(feature = "sanity")]
2524
use crate::util::sanity::sanity_checker::*;
26-
use crate::util::side_metadata::meta_bytes_per_chunk;
2725
use crate::util::OpaquePointer;
28-
use crate::vm::ObjectModel;
2926
use crate::vm::*;
3027
use crate::{mmtk::MMTK, plan::barriers::BarrierSelector};
28+
use crate::{plan::global::BasePlan, util::side_metadata::SideMetadataSpec};
3129
use enum_map::EnumMap;
3230
use std::sync::atomic::{AtomicBool, Ordering};
3331
use std::sync::Arc;
@@ -174,16 +172,8 @@ impl<VM: VMBinding> Plan for GenCopy<VM> {
174172
self.in_nursery.load(Ordering::SeqCst)
175173
}
176174

177-
fn global_side_metadata_per_chunk(&self) -> usize {
178-
let mut side_metadata_per_chunk = if !VM::VMObjectModel::HAS_GC_BYTE {
179-
meta_bytes_per_chunk(3, 1)
180-
} else {
181-
0
182-
};
183-
if super::ACTIVE_BARRIER == BarrierSelector::ObjectBarrier {
184-
side_metadata_per_chunk += LOGGING_META.meta_bytes_per_chunk();
185-
}
186-
side_metadata_per_chunk
175+
fn global_side_metadata_specs(&self) -> &[SideMetadataSpec] {
176+
&self.common().global_metadata_specs
187177
}
188178
}
189179

@@ -195,6 +185,11 @@ impl<VM: VMBinding> GenCopy<VM> {
195185
scheduler: &'static MMTkScheduler<VM>,
196186
) -> Self {
197187
let mut heap = HeapMeta::new(HEAP_START, HEAP_END);
188+
let global_metadata_specs = if super::ACTIVE_BARRIER == BarrierSelector::ObjectBarrier {
189+
vec![LOGGING_META]
190+
} else {
191+
vec![]
192+
};
198193

199194
GenCopy {
200195
nursery: CopySpace::new(
@@ -225,7 +220,14 @@ impl<VM: VMBinding> GenCopy<VM> {
225220
mmapper,
226221
&mut heap,
227222
),
228-
common: CommonPlan::new(vm_map, mmapper, options, heap, &GENCOPY_CONSTRAINTS),
223+
common: CommonPlan::new(
224+
vm_map,
225+
mmapper,
226+
options,
227+
heap,
228+
&GENCOPY_CONSTRAINTS,
229+
&&global_metadata_specs,
230+
),
229231
in_nursery: AtomicBool::default(),
230232
scheduler,
231233
}

src/plan/gencopy/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,17 @@ pub const NO_SLOW: bool = false;
2424

2525
pub use self::global::GENCOPY_CONSTRAINTS;
2626

27+
#[cfg(feature = "side_gc_header")]
28+
use crate::util::gc_byte;
2729
use crate::util::side_metadata::*;
2830

2931
const LOGGING_META: SideMetadataSpec = SideMetadataSpec {
3032
scope: SideMetadataScope::Global,
31-
offset: 0,
33+
#[cfg(not(feature = "side_gc_header"))]
34+
offset: GLOBAL_SIDE_METADATA_BASE_ADDRESS.as_usize(),
35+
#[cfg(feature = "side_gc_header")]
36+
offset: GLOBAL_SIDE_METADATA_BASE_ADDRESS.as_usize()
37+
+ metadata_address_range_size(gc_byte::SIDE_GC_BYTE_SPEC),
3238
log_num_of_bits: 0,
3339
log_min_obj_size: 3,
3440
};

src/plan/global.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use super::controller_collector_context::ControllerCollectorContext;
44
use super::PlanConstraints;
5-
use crate::mmtk::MMTK;
65
use crate::plan::transitive_closure::TransitiveClosure;
76
use crate::plan::Mutator;
87
use crate::policy::immortalspace::ImmortalSpace;
@@ -14,6 +13,7 @@ use crate::util::alloc::allocators::AllocatorSelector;
1413
#[cfg(feature = "analysis")]
1514
use crate::util::analysis::AnalysisManager;
1615
use crate::util::conversions::bytes_to_pages;
16+
use crate::util::gc_byte;
1717
use crate::util::heap::layout::heap_layout::Mmapper;
1818
use crate::util::heap::layout::heap_layout::VMMap;
1919
use crate::util::heap::layout::map::Map;
@@ -25,6 +25,7 @@ use crate::util::statistics::stats::Stats;
2525
use crate::util::OpaquePointer;
2626
use crate::util::{Address, ObjectReference};
2727
use crate::vm::*;
28+
use crate::{mmtk::MMTK, util::side_metadata::SideMetadataSpec};
2829
use downcast_rs::Downcast;
2930
use enum_map::EnumMap;
3031
use std::cell::UnsafeCell;
@@ -341,8 +342,8 @@ pub trait Plan: 'static + Sync + Send + Downcast {
341342
}
342343
}
343344

344-
fn global_side_metadata_per_chunk(&self) -> usize {
345-
0
345+
fn global_side_metadata_specs(&self) -> &[SideMetadataSpec] {
346+
&[]
346347
}
347348
}
348349

@@ -712,6 +713,7 @@ CommonPlan is for representing state and features used by _many_ plans, but that
712713
pub struct CommonPlan<VM: VMBinding> {
713714
pub unsync: UnsafeCell<CommonUnsync<VM>>,
714715
pub base: BasePlan<VM>,
716+
pub global_metadata_specs: Vec<SideMetadataSpec>,
715717
}
716718

717719
pub struct CommonUnsync<VM: VMBinding> {
@@ -726,7 +728,14 @@ impl<VM: VMBinding> CommonPlan<VM> {
726728
options: Arc<UnsafeOptionsWrapper>,
727729
mut heap: HeapMeta,
728730
constraints: &'static PlanConstraints,
731+
global_side_metadata_specs: &[SideMetadataSpec],
729732
) -> CommonPlan<VM> {
733+
let mut specs = if cfg!(feature = "side_gc_header") {
734+
vec![gc_byte::SIDE_GC_BYTE_SPEC]
735+
} else {
736+
vec![]
737+
};
738+
specs.extend_from_slice(global_side_metadata_specs);
730739
CommonPlan {
731740
unsync: UnsafeCell::new(CommonUnsync {
732741
immortal: ImmortalSpace::new(
@@ -749,6 +758,7 @@ impl<VM: VMBinding> CommonPlan<VM> {
749758
),
750759
}),
751760
base: BasePlan::new(vm_map, mmapper, options, heap, constraints),
761+
global_metadata_specs: specs,
752762
}
753763
}
754764

src/plan/marksweep/global.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ impl<VM: VMBinding> MarkSweep<VM> {
127127
) -> Self {
128128
let heap = HeapMeta::new(HEAP_START, HEAP_END);
129129
MarkSweep {
130-
common: CommonPlan::new(vm_map, mmapper, options, heap, &MS_CONSTRAINTS),
130+
common: CommonPlan::new(vm_map, mmapper, options, heap, &MS_CONSTRAINTS, &[]),
131131
ms: MallocSpace::new(),
132132
}
133133
}

src/plan/semispace/global.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use super::gc_work::{SSCopyContext, SSProcessEdges};
2-
use crate::mmtk::MMTK;
3-
use crate::plan::global::BasePlan;
42
use crate::plan::global::CommonPlan;
53
use crate::plan::global::GcStatus;
64
use crate::plan::semispace::mutator::ALLOCATOR_MAPPING;
@@ -22,10 +20,9 @@ use crate::util::heap::VMRequest;
2220
use crate::util::options::UnsafeOptionsWrapper;
2321
#[cfg(feature = "sanity")]
2422
use crate::util::sanity::sanity_checker::*;
25-
use crate::util::side_metadata::meta_bytes_per_chunk;
2623
use crate::util::OpaquePointer;
27-
use crate::vm::ObjectModel;
28-
use crate::vm::VMBinding;
24+
use crate::{mmtk::MMTK, util::side_metadata::SideMetadataSpec};
25+
use crate::{plan::global::BasePlan, vm::VMBinding};
2926
use std::sync::atomic::{AtomicBool, Ordering};
3027
use std::sync::Arc;
3128

@@ -141,12 +138,8 @@ impl<VM: VMBinding> Plan for SemiSpace<VM> {
141138
&self.common
142139
}
143140

144-
fn global_side_metadata_per_chunk(&self) -> usize {
145-
if !VM::VMObjectModel::HAS_GC_BYTE {
146-
meta_bytes_per_chunk(3, 1)
147-
} else {
148-
0
149-
}
141+
fn global_side_metadata_specs(&self) -> &[SideMetadataSpec] {
142+
&self.common().global_metadata_specs
150143
}
151144
}
152145

@@ -179,7 +172,7 @@ impl<VM: VMBinding> SemiSpace<VM> {
179172
mmapper,
180173
&mut heap,
181174
),
182-
common: CommonPlan::new(vm_map, mmapper, options, heap, &SS_CONSTRAINTS),
175+
common: CommonPlan::new(vm_map, mmapper, options, heap, &SS_CONSTRAINTS, &[]),
183176
}
184177
}
185178

src/policy/lockfreeimmortalspace.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,14 @@ impl<VM: VMBinding> Space<VM> for LockFreeImmortalSpace<VM> {
9292
self.limit = AVAILABLE_START + total_bytes;
9393
// Eagerly memory map the entire heap (also zero all the memory)
9494
crate::util::memory::dzmmap(AVAILABLE_START, total_bytes).unwrap();
95-
if !try_map_metadata_space(
95+
if try_map_metadata_space(
9696
AVAILABLE_START,
9797
total_bytes,
98-
VM::VMActivePlan::global().global_side_metadata_per_chunk(),
99-
self.local_side_metadata_per_chunk(),
100-
) {
98+
VM::VMActivePlan::global().global_side_metadata_specs(),
99+
self.local_side_metadata_specs(),
100+
)
101+
.is_err()
102+
{
101103
// TODO(Javad): handle meta space allocation failure
102104
panic!("failed to mmap meta memory");
103105
}

0 commit comments

Comments
 (0)