Skip to content

Commit c1effcd

Browse files
authored
Julia's stock GC trigger heuristics (#154)
This PR fixes Julia's GC trigger option/heuristics and enables it as default (by changing the initial values to in `mmtk-gc.c`: mmtk/julia#54).
1 parent c1ccd57 commit c1effcd

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

mmtk/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ edition = "2018"
1010
[package.metadata.julia]
1111
# Our CI matches the following line and extract mmtk/julia. If this line is updated, please check ci yaml files and make sure it works.
1212
julia_repo = "https://github.com/mmtk/julia.git"
13-
julia_version = "0ac54e680f9a8b57bb1fd8ef04919ce9898ae77b"
13+
julia_version = "5bb4714e34084ae851d2b6ecb2c1da0242c912c0"
1414

1515
[lib]
1616
crate-type = ["cdylib"]

mmtk/src/api.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,12 @@ pub extern "C" fn mmtk_gc_init(
6868
// If MMTK_GC_TRIGGER is not set, then use the min/max heap size from the arguments.
6969
Err(_) => {
7070
let success;
71-
if min_heap_size != 0 {
71+
if min_heap_size == 0 && max_heap_size == 0 {
72+
success = builder
73+
.options
74+
.gc_trigger
75+
.set(mmtk::util::options::GCTriggerSelector::Delegated);
76+
} else if min_heap_size != 0 {
7277
info!(
7378
"Setting mmtk heap size to a variable size with min-max of {}-{} (in bytes)",
7479
min_heap_size, max_heap_size
@@ -271,9 +276,9 @@ pub extern "C" fn mmtk_handle_user_collection_request(tls: VMMutatorThread, coll
271276
// auto
272277
0 => memory_manager::handle_user_collection_request::<JuliaVM>(&SINGLETON, tls),
273278
// full
274-
1 => SINGLETON.handle_user_collection_request(tls, true, true),
279+
1 => SINGLETON.handle_user_collection_request(tls, false, true),
275280
// incremental
276-
2 => SINGLETON.handle_user_collection_request(tls, true, false),
281+
2 => SINGLETON.handle_user_collection_request(tls, false, false),
277282
_ => unreachable!(),
278283
}
279284
}

mmtk/src/gc_trigger.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ pub struct JuliaGCTrigger {
3939
interval_all_threads: AtomicUsize,
4040
actual_allocd: AtomicUsize,
4141
prev_sweep_full: AtomicBool,
42-
42+
/// The number of pending allocation pages. The allocation requests for them have failed, and a GC is triggered.
43+
/// We will need to take them into consideration so that the new heap size can accomodate those allocations.
44+
pending_pages: AtomicUsize,
4345
last_recorded_reserved_pages: AtomicUsize,
4446
}
4547

@@ -79,14 +81,18 @@ impl JuliaGCTrigger {
7981
actual_allocd: AtomicUsize::new(0),
8082
prev_sweep_full: AtomicBool::new(true),
8183
last_recorded_reserved_pages: AtomicUsize::new(0),
84+
pending_pages: AtomicUsize::new(0),
8285
}
8386
}
8487
}
8588

8689
impl GCTriggerPolicy<JuliaVM> for JuliaGCTrigger {
8790
fn on_gc_start(&self, mmtk: &'static MMTK<JuliaVM>) {
8891
let reserved_pages_in_last_gc = self.last_recorded_reserved_pages.load(Ordering::Relaxed);
89-
let reserved_pages_now = mmtk.get_plan().get_reserved_pages();
92+
// reserved pages now should include pending allocations
93+
let reserved_pages_now =
94+
mmtk.get_plan().get_reserved_pages() + self.pending_pages.load(Ordering::SeqCst);
95+
9096
self.last_recorded_reserved_pages
9197
.store(reserved_pages_now, Ordering::Relaxed);
9298
self.actual_allocd.store(
@@ -110,7 +116,8 @@ impl GCTriggerPolicy<JuliaVM> for JuliaGCTrigger {
110116
let n_mutators = crate::active_plan::VMActivePlan::number_of_mutators();
111117

112118
let reserved_pages_before_gc = self.last_recorded_reserved_pages.load(Ordering::Relaxed);
113-
let reserved_pages_now = mmtk.get_plan().get_reserved_pages();
119+
let reserved_pages_now =
120+
mmtk.get_plan().get_reserved_pages() + self.pending_pages.load(Ordering::SeqCst);
114121
let freed = conversions::pages_to_bytes(
115122
reserved_pages_before_gc.saturating_sub(reserved_pages_now),
116123
);
@@ -122,7 +129,7 @@ impl GCTriggerPolicy<JuliaVM> for JuliaGCTrigger {
122129
// ignore large frontier (large frontier means the bytes of pointers reachable from the remset is larger than the default collect interval)
123130
let gc_auto = !mmtk.is_user_triggered_collection();
124131
let not_freed_enough = gc_auto
125-
&& (freed as f64) < (self.actual_allocd.load(Ordering::Relaxed) as f64 * 0.7f64);
132+
&& ((freed as f64) < (self.actual_allocd.load(Ordering::Relaxed) as f64 * 0.7f64));
126133
let mut sweep_full = false;
127134
if gc_auto {
128135
if not_freed_enough {
@@ -240,6 +247,13 @@ impl GCTriggerPolicy<JuliaVM> for JuliaGCTrigger {
240247
self.interval.load(Ordering::Relaxed) * n_mutators / 2,
241248
Ordering::Relaxed,
242249
);
250+
251+
// Clear pending allocation pages at the end of GC, no matter we used it or not.
252+
self.pending_pages.store(0, Ordering::SeqCst);
253+
}
254+
255+
fn on_pending_allocation(&self, pages: usize) {
256+
self.pending_pages.fetch_add(pages, Ordering::SeqCst);
243257
}
244258

245259
/// Is a GC required now?
@@ -249,9 +263,19 @@ impl GCTriggerPolicy<JuliaVM> for JuliaGCTrigger {
249263
space: Option<SpaceStats<JuliaVM>>,
250264
plan: &dyn Plan<VM = JuliaVM>,
251265
) -> bool {
266+
let reserved_pages_now = plan.get_reserved_pages();
267+
let reserved_pages_before_gc = self.last_recorded_reserved_pages.load(Ordering::Relaxed);
268+
252269
let allocd_so_far = conversions::pages_to_bytes(
253-
plan.get_reserved_pages() - self.last_recorded_reserved_pages.load(Ordering::Relaxed),
270+
reserved_pages_now.saturating_sub(reserved_pages_before_gc),
254271
);
272+
273+
trace!(
274+
"Reserved now = {}, last recorded reserved = {}, Allocd so far: {}. interval_all_threads = {}",
275+
plan.get_reserved_pages(), self.last_recorded_reserved_pages.load(Ordering::Relaxed), allocd_so_far,
276+
self.interval_all_threads.load(Ordering::Relaxed)
277+
);
278+
255279
// Check against interval_all_threads, as we count allocation from all threads.
256280
if allocd_so_far > self.interval_all_threads.load(Ordering::Relaxed) {
257281
return true;

0 commit comments

Comments
 (0)