Skip to content

Commit c2a79ad

Browse files
committed
Adding feature to query the fragmentation of immixspace
1 parent 86a94ca commit c2a79ad

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ malloc_counted_size = []
152152
# Count the size of all live objects in GC
153153
count_live_bytes_in_gc = []
154154

155+
# Count the size of live objects in immixspace (the ones that can actually be opportunistically moved)
156+
count_live_bytes_immixspace = []
157+
155158
# Workaround a problem where bpftrace scripts (see tools/tracing/timeline/capture.bt) cannot
156159
# capture the type names of work packets.
157160
bpftrace_workaround = []

src/global_state.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ pub struct GlobalState {
4343
/// This stores the size in bytes for all the live objects in last GC. This counter is only updated in the GC release phase.
4444
#[cfg(feature = "count_live_bytes_in_gc")]
4545
pub(crate) live_bytes_in_last_gc: AtomicUsize,
46+
/// These keep track of the fragmentation rate in immixspace
47+
#[cfg(feature = "count_live_bytes_immixspace")]
48+
pub(crate) live_bytes_in_immixspace: AtomicUsize,
49+
#[cfg(feature = "count_live_bytes_immixspace")]
50+
pub(crate) fragmentation_rate_in_immixspace: AtomicUsize,
4651
}
4752

4853
impl GlobalState {
@@ -188,6 +193,38 @@ impl GlobalState {
188193
pub fn set_live_bytes_in_last_gc(&self, size: usize) {
189194
self.live_bytes_in_last_gc.store(size, Ordering::SeqCst);
190195
}
196+
197+
#[cfg(feature = "count_live_bytes_immixspace")]
198+
pub fn get_live_bytes_in_last_gc(&self) -> usize {
199+
self.live_bytes_in_immixspace.load(Ordering::SeqCst)
200+
}
201+
202+
#[cfg(feature = "count_live_bytes_immixspace")]
203+
pub fn set_live_bytes_in_immixspace(&self, size: usize) {
204+
self.live_bytes_in_immixspace.store(size, Ordering::SeqCst);
205+
}
206+
207+
#[cfg(feature = "count_live_bytes_immixspace")]
208+
pub fn get_live_bytes_in_immixspace(&self) -> usize {
209+
self.live_bytes_in_immixspace.load(Ordering::SeqCst)
210+
}
211+
212+
#[cfg(feature = "count_live_bytes_immixspace")]
213+
pub fn increase_live_bytes_in_immixspace_by(&self, size: usize) {
214+
self.live_bytes_in_immixspace
215+
.fetch_add(size, Ordering::SeqCst);
216+
}
217+
218+
#[cfg(feature = "count_live_bytes_immixspace")]
219+
pub fn get_fragmentation_rate_in_immixspace(&self) -> usize {
220+
self.fragmentation_rate_in_immixspace.load(Ordering::SeqCst)
221+
}
222+
223+
#[cfg(feature = "count_live_bytes_immixspace")]
224+
pub fn set_fragmentation_rate_in_immixspace(&self, size: usize) {
225+
self.fragmentation_rate_in_immixspace
226+
.store(size, Ordering::SeqCst);
227+
}
191228
}
192229

193230
impl Default for GlobalState {
@@ -209,6 +246,10 @@ impl Default for GlobalState {
209246
malloc_bytes: AtomicUsize::new(0),
210247
#[cfg(feature = "count_live_bytes_in_gc")]
211248
live_bytes_in_last_gc: AtomicUsize::new(0),
249+
#[cfg(feature = "count_live_bytes_immixspace")]
250+
live_bytes_in_immixspace: AtomicUsize::new(0),
251+
#[cfg(feature = "count_live_bytes_immixspace")]
252+
fragmentation_rate_in_immixspace: AtomicUsize::new(0),
212253
}
213254
}
214255
}

src/memory_manager.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,19 @@ pub fn live_bytes_in_last_gc<VM: VMBinding>(mmtk: &MMTK<VM>) -> usize {
557557
mmtk.state.live_bytes_in_last_gc.load(Ordering::SeqCst)
558558
}
559559

560+
/// Return the percentage of fragmentation of the immixspace (e.g. 42.98 percent). To do that we count the size of every live object
561+
/// in the immixspace. Since MMTk accounts for memory in pages, we return the ratio between this number and
562+
/// the number of used bytes (according to the used pages by the immixspace).
563+
/// The value returned by this method is only updated when we finish tracing in a GC. A recommended timing
564+
/// to call this method is at the end of a GC (e.g. when the runtime is about to resume threads).
565+
#[cfg(feature = "count_live_bytes_immixspace")]
566+
pub fn fragmentation_rate_in_immixspace<VM: VMBinding>(mmtk: &MMTK<VM>) -> f64 {
567+
mmtk.state
568+
.fragmentation_rate_in_immixspace
569+
.load(Ordering::SeqCst) as f64
570+
/ 100.0
571+
}
572+
560573
/// Return the starting address of the heap. *Note that currently MMTk uses
561574
/// a fixed address range as heap.*
562575
pub fn starting_heap_address() -> Address {

src/policy/immix/immixspace.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,13 @@ impl<VM: VMBinding> crate::policy::gc_work::PolicyTraceObject<VM> for ImmixSpace
217217
debug_assert!(self.in_space(object));
218218
self.mark_lines(object);
219219
}
220+
221+
// count the bytes for each object in immixspace to
222+
// check for fragmentation
223+
#[cfg(feature = "count_live_bytes_immixspace")]
224+
self.common
225+
.global_state
226+
.increase_live_bytes_in_immixspace_by(VM::VMObjectModel::get_current_size(object));
220227
}
221228

222229
fn may_move_objects<const KIND: TraceKind>() -> bool {
@@ -464,6 +471,31 @@ impl<VM: VMBinding> ImmixSpace<VM> {
464471

465472
self.lines_consumed.store(0, Ordering::Relaxed);
466473

474+
// calculate the fragmentation rate
475+
#[cfg(feature = "count_live_bytes_immixspace")]
476+
{
477+
trace!(
478+
"Live bytes in immixspace = {}",
479+
self.common.global_state.get_live_bytes_in_immixspace()
480+
);
481+
trace!("Reserved pages in immixspace = {}", self.reserved_pages());
482+
483+
trace!(
484+
"Reserved bytes in immixspace = {}",
485+
self.reserved_pages() << LOG_BYTES_IN_PAGE
486+
);
487+
let f_rate: f64 = self.common.global_state.get_live_bytes_in_immixspace() as f64
488+
/ (self.reserved_pages() << LOG_BYTES_IN_PAGE) as f64;
489+
490+
let f_rate_usize: usize = (f_rate * 10000.0) as usize;
491+
492+
debug_assert!(f_rate <= 1.0 && f_rate >= 0.0);
493+
494+
self.common
495+
.global_state
496+
.set_fragmentation_rate_in_immixspace(f_rate_usize);
497+
}
498+
467499
did_defrag
468500
}
469501

0 commit comments

Comments
 (0)