-
Notifications
You must be signed in to change notification settings - Fork 79
Adding feature to query the fragmentation of immixspace #1089
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 8 commits
c2a79ad
f081e4f
530051b
ee21a9c
bd3305f
1f39198
06284e1
1547428
184822c
f294948
6f1c924
aeb3aeb
4cfac97
d56c3b9
e787b2d
d5f993c
986ceb0
cbbcfd8
7039d5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,6 +54,9 @@ pub struct ImmixSpace<VM: VMBinding> { | |
scheduler: Arc<GCWorkScheduler<VM>>, | ||
/// Some settings for this space | ||
space_args: ImmixSpaceArgs, | ||
/// Keeping track of live bytes | ||
#[cfg(feature = "dump_memory_stats")] | ||
live_bytes: AtomicUsize, | ||
} | ||
|
||
/// Some arguments for Immix Space. | ||
|
@@ -217,6 +220,10 @@ impl<VM: VMBinding> crate::policy::gc_work::PolicyTraceObject<VM> for ImmixSpace | |
debug_assert!(self.in_space(object)); | ||
self.mark_lines(object); | ||
} | ||
|
||
// count the bytes for each object in immixspace | ||
#[cfg(feature = "dump_memory_stats")] | ||
self.increase_live_bytes(VM::VMObjectModel::get_current_size(object)); | ||
} | ||
|
||
fn may_move_objects<const KIND: TraceKind>() -> bool { | ||
|
@@ -315,6 +322,8 @@ impl<VM: VMBinding> ImmixSpace<VM> { | |
mark_state: Self::MARKED_STATE, | ||
scheduler: scheduler.clone(), | ||
space_args, | ||
#[cfg(feature = "dump_memory_stats")] | ||
live_bytes: AtomicUsize::new(0), | ||
} | ||
} | ||
|
||
|
@@ -436,6 +445,9 @@ impl<VM: VMBinding> ImmixSpace<VM> { | |
self.scheduler.work_buckets[WorkBucketStage::ClearVOBits].bulk_add(work_packets); | ||
} | ||
} | ||
|
||
#[cfg(feature = "dump_memory_stats")] | ||
self.set_live_bytes(0); | ||
} | ||
|
||
/// Release for the immix space. This is called when a GC finished. | ||
|
@@ -467,6 +479,62 @@ impl<VM: VMBinding> ImmixSpace<VM> { | |
did_defrag | ||
} | ||
|
||
#[cfg(feature = "dump_memory_stats")] | ||
pub(crate) fn dump_memory_stats(&self) { | ||
#[derive(Default)] | ||
struct Dist { | ||
live_blocks: usize, | ||
live_lines: usize, | ||
} | ||
let mut dist = Dist::default(); | ||
for chunk in self.chunk_map.all_chunks() { | ||
if !self.address_in_space(chunk.start()) { | ||
continue; | ||
} | ||
|
||
for block in chunk | ||
.iter_region::<Block>() | ||
.filter(|b| b.get_state() != BlockState::Unallocated) | ||
{ | ||
dist.live_blocks += 1; | ||
match block.get_state() { | ||
BlockState::Marked => { | ||
panic!("At this point the block should have been swept already"); | ||
} | ||
BlockState::Unmarked => { | ||
// Block is unmarked and cannot be reused (has no holes) | ||
dist.live_lines += Block::LINES; | ||
} | ||
BlockState::Reusable { unavailable_lines } => { | ||
dist.live_lines += unavailable_lines as usize; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this number equivalent to linearly scan the line mark table and manually check the line mark bytes? Probably better to add an assertion to double check. Same as L506. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added an assertion in the latest commit that compares the number of live lines by just iterating the lines in the block and checking the mark table with the number from the block state. Is that what you meant? |
||
} | ||
BlockState::Unallocated => {} | ||
} | ||
} | ||
} | ||
|
||
println!( | ||
"{} immixspace", | ||
chrono::offset::Local::now().format("%Y-%m-%d %H:%M:%S") | ||
); | ||
println!("\tLive bytes = {}", self.get_live_bytes()); | ||
println!("\tReserved pages = {}", self.reserved_pages()); | ||
println!( | ||
"\tReserved pages (bytes) = {}", | ||
self.reserved_pages() << LOG_BYTES_IN_PAGE | ||
); | ||
println!("\tLive blocks = {}", dist.live_blocks); | ||
println!( | ||
"\tLive blocks (bytes) = {}", | ||
dist.live_blocks << Block::LOG_BYTES | ||
); | ||
println!("\tLive lines = {}", dist.live_lines); | ||
println!( | ||
"\tLive lines (bytes) = {}", | ||
dist.live_lines << Line::LOG_BYTES | ||
); | ||
} | ||
|
||
/// Generate chunk sweep tasks | ||
fn generate_sweep_tasks(&self) -> Vec<Box<dyn GCWork<VM>>> { | ||
self.defrag.mark_histograms.lock().clear(); | ||
|
@@ -807,6 +875,21 @@ impl<VM: VMBinding> ImmixSpace<VM> { | |
self.mark_lines(object); | ||
} | ||
} | ||
|
||
#[cfg(feature = "dump_memory_stats")] | ||
pub fn get_live_bytes(&self) -> usize { | ||
self.live_bytes.load(Ordering::SeqCst) | ||
} | ||
|
||
#[cfg(feature = "dump_memory_stats")] | ||
pub fn set_live_bytes(&self, size: usize) { | ||
self.live_bytes.store(size, Ordering::SeqCst) | ||
} | ||
|
||
#[cfg(feature = "dump_memory_stats")] | ||
pub fn increase_live_bytes(&self, size: usize) { | ||
self.live_bytes.fetch_add(size, Ordering::SeqCst); | ||
} | ||
} | ||
|
||
/// A work packet to prepare each block for a major GC. | ||
|
Uh oh!
There was an error while loading. Please reload this page.