Skip to content
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

Add bit to the GC tag to turn GC in image search O(1) and also increase gc interval when encountering many pointers #49185

Merged
merged 2 commits into from
Mar 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2390,7 +2390,7 @@ FORCE_INLINE void gc_mark_outrefs(jl_ptls_t ptls, jl_gc_markqueue_t *mq, void *_
int update_meta = __likely(!meta_updated && !gc_verifying);
int foreign_alloc = 0;
// directly point at eyt_obj_in_img to encourage inlining
if (update_meta && eyt_obj_in_img(new_obj)) {
if (update_meta && o->bits.in_image) {
foreign_alloc = 1;
update_meta = 0;
}
Expand Down Expand Up @@ -3059,12 +3059,14 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)

// update heuristics only if this GC was automatically triggered
if (collection == JL_GC_AUTO) {
if (not_freed_enough) {
gc_num.interval = gc_num.interval * 2;
}
if (large_frontier) {
sweep_full = 1;
gc_num.interval = last_long_collect_interval;
}
if (not_freed_enough || large_frontier) {
gc_num.interval = gc_num.interval * 2;
}

size_t maxmem = 0;
#ifdef _P64
// on a big memory machine, increase max_collect_interval to totalmem / nthreads / 2
Expand Down Expand Up @@ -3097,6 +3099,7 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)
// on the first collection after sweep_full, and the current scan
perm_scanned_bytes = 0;
promoted_bytes = 0;
last_long_collect_interval = gc_num.interval;
}
scanned_bytes = 0;
// 6. start sweeping
Expand Down Expand Up @@ -3166,22 +3169,34 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)
live_bytes += -gc_num.freed + gc_num.since_sweep;

if (collection == JL_GC_AUTO) {
//If we aren't freeing enough or are seeing lots and lots of pointers let it increase faster
if(!not_freed_enough || large_frontier) {
int64_t tot = 2 * (live_bytes + gc_num.since_sweep) / 3;
if (gc_num.interval > tot) {
gc_num.interval = tot;
last_long_collect_interval = tot;
}
// If the current interval is larger than half the live data decrease the interval
int64_t half = live_bytes/2;
if (gc_num.interval > half) gc_num.interval = half;
} else {
int64_t half = (live_bytes / 2);
if (gc_num.interval > half)
gc_num.interval = half;
}

// But never go below default
if (gc_num.interval < default_collect_interval) gc_num.interval = default_collect_interval;
}

if (gc_num.interval + live_bytes > max_total_memory) {
if (live_bytes < max_total_memory) {
gc_num.interval = max_total_memory - live_bytes;
last_long_collect_interval = max_total_memory - live_bytes;
}
else {
// We can't stay under our goal so let's go back to
// the minimum interval and hope things get better
gc_num.interval = default_collect_interval;
}
}
}

gc_time_summary(sweep_full, t_start, gc_end_time, gc_num.freed,
Expand Down
1 change: 1 addition & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ typedef struct _jl_value_t jl_value_t;

struct _jl_taggedvalue_bits {
uintptr_t gc:2;
uintptr_t in_image:1;
};

JL_EXTENSION struct _jl_taggedvalue_t {
Expand Down
1 change: 1 addition & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ static inline void memmove_refs(void **dstp, void *const *srcp, size_t n) JL_NOT
#define GC_MARKED 1 // reachable and young
#define GC_OLD 2 // if it is reachable it will be marked as old
#define GC_OLD_MARKED (GC_OLD | GC_MARKED) // reachable and old
#define GC_IN_IMAGE 4

// useful constants
extern jl_methtable_t *jl_type_type_mt JL_GLOBALLY_ROOTED;
Expand Down
7 changes: 5 additions & 2 deletions src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,7 @@ void gc_sweep_sysimg(void)
last_pos = pos;
jl_taggedvalue_t *o = (jl_taggedvalue_t *)(base + pos);
o->bits.gc = GC_OLD;
assert(o->bits.in_image == 1);
}
}
}
Expand Down Expand Up @@ -2811,7 +2812,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
*base = image_base;

s.s = &sysimg;
jl_read_reloclist(&s, s.link_ids_gctags, GC_OLD); // gctags
jl_read_reloclist(&s, s.link_ids_gctags, GC_OLD | GC_IN_IMAGE); // gctags
size_t sizeof_tags = ios_pos(&relocs);
(void)sizeof_tags;
jl_read_reloclist(&s, s.link_ids_relocs, 0); // general relocs
Expand Down Expand Up @@ -2922,7 +2923,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
arraylist_push(&cleanup_list, (void*)obj);
}
if (tag)
*pfld = (uintptr_t)newobj | GC_OLD;
*pfld = (uintptr_t)newobj | GC_OLD | GC_IN_IMAGE;
else
*pfld = (uintptr_t)newobj;
assert(!(image_base < (char*)newobj && (char*)newobj <= image_base + sizeof_sysimg + sizeof(uintptr_t)));
Expand Down Expand Up @@ -2965,6 +2966,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
memset(o, 0xba, sizeof(jl_value_t*) + sizeof(jl_datatype_t));
else
memset(o, 0xba, sizeof(jl_value_t*) + 0); // singleton
o->bits.in_image = 1;
}
arraylist_grow(&cleanup_list, -cleanup_list.len);
// finally cache all our new types now
Expand Down Expand Up @@ -3032,6 +3034,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
jl_value_t *t = jl_typeof(item);
if (t == (jl_value_t*)jl_method_instance_type)
memset(o, 0xba, sizeof(jl_value_t*) * 3); // only specTypes and sparams fields stored
o->bits.in_image = 1;
}
arraylist_free(&cleanup_list);
for (size_t i = 0; i < s.fixup_objs.len; i++) {
Expand Down