@@ -27,6 +27,8 @@ static jl_gc_callback_list_t *gc_cblist_post_gc;
27
27
static jl_gc_callback_list_t * gc_cblist_notify_external_alloc ;
28
28
static jl_gc_callback_list_t * gc_cblist_notify_external_free ;
29
29
30
+ static uint64_t t_start = 0 ;
31
+
30
32
#define gc_invoke_callbacks (ty , list , args ) \
31
33
do { \
32
34
for (jl_gc_callback_list_t *cb = list; \
@@ -1847,14 +1849,19 @@ STATIC_INLINE int gc_mark_scan_objarray(jl_ptls_t ptls, jl_gc_mark_sp_t *sp,
1847
1849
jl_value_t * * begin , jl_value_t * * end ,
1848
1850
jl_value_t * * pnew_obj , uintptr_t * ptag , uint8_t * pbits )
1849
1851
{
1852
+
1853
+
1850
1854
(void )jl_assume (objary == (gc_mark_objarray_t * )sp -> data );
1851
1855
for (; begin < end ; begin += objary -> step ) {
1852
1856
* pnew_obj = * begin ;
1853
1857
if (* pnew_obj )
1854
1858
verify_parent2 ("obj array" , objary -> parent , begin , "elem(%d)" ,
1855
1859
gc_slot_to_arrayidx (objary -> parent , begin ));
1856
- if (!gc_try_setmark (* pnew_obj , & objary -> nptr , ptag , pbits ))
1857
- continue ;
1860
+
1861
+ if (!gc_try_setmark (* pnew_obj , & objary -> nptr , ptag , pbits )) {
1862
+ continue ;
1863
+ }
1864
+
1858
1865
begin += objary -> step ;
1859
1866
// Found an object to mark
1860
1867
if (begin < end ) {
@@ -2547,7 +2554,7 @@ mark: {
2547
2554
jl_value_t * * data = jl_svec_data (new_obj );
2548
2555
size_t dtsz = l * sizeof (void * ) + sizeof (jl_svec_t );
2549
2556
if (update_meta )
2550
- gc_setmark (ptls , o , bits , dtsz );
2557
+ gc_setmark (ptls , o , bits , dtsz );
2551
2558
else if (foreign_alloc )
2552
2559
objprofile_count (vt , bits == GC_OLD_MARKED , dtsz );
2553
2560
uintptr_t nptr = (l << 2 ) | (bits & GC_OLD );
@@ -2984,6 +2991,7 @@ static void jl_gc_premark(jl_ptls_t ptls2)
2984
2991
ptls2 -> heap .remset -> len = 0 ;
2985
2992
ptls2 -> heap .remset_nptr = 0 ;
2986
2993
2994
+
2987
2995
// avoid counting remembered objects & bindings twice
2988
2996
// in `perm_scanned_bytes`
2989
2997
size_t len = remset -> len ;
@@ -3125,6 +3133,7 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)
3125
3133
int64_t live_sz_est = scanned_bytes + perm_scanned_bytes ;
3126
3134
int64_t estimate_freed = live_sz_ub - live_sz_est ;
3127
3135
3136
+
3128
3137
gc_verify (ptls );
3129
3138
3130
3139
gc_stats_all_pool ();
@@ -3134,50 +3143,48 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)
3134
3143
gc_num .total_allocd += gc_num .since_sweep ;
3135
3144
if (!prev_sweep_full )
3136
3145
promoted_bytes += perm_scanned_bytes - last_perm_scanned_bytes ;
3146
+
3137
3147
// 5. next collection decision
3138
3148
int not_freed_enough = (collection == JL_GC_AUTO ) && estimate_freed < (7 * (actual_allocd /10 ));
3149
+
3139
3150
int nptr = 0 ;
3140
3151
for (int i = 0 ;i < jl_n_threads ;i ++ )
3141
3152
nptr += jl_all_tls_states [i ]-> heap .remset_nptr ;
3142
- int large_frontier = nptr * sizeof (void * ) >= default_collect_interval ; // many pointers in the intergen frontier => "quick" mark is not quick
3153
+
3154
+ int large_frontier = nptr * sizeof (void * ) >= default_collect_interval ;
3155
+
3156
+ // many pointers in the intergen frontier => "quick" mark is not quick
3143
3157
// trigger a full collection if the number of live bytes doubles since the last full
3144
3158
// collection and then remains at least that high for a while.
3145
3159
if (grown_heap_age == 0 ) {
3146
- if (live_bytes > 2 * last_full_live )
3147
- grown_heap_age = 1 ;
3160
+ if (live_bytes > 2 * last_full_live )
3161
+ grown_heap_age = 1 ;
3148
3162
}
3149
3163
else if (live_bytes >= last_live_bytes ) {
3150
3164
grown_heap_age ++ ;
3151
3165
}
3166
+
3152
3167
int sweep_full = 0 ;
3153
3168
int recollect = 0 ;
3154
- if ((large_frontier ||
3155
- ((not_freed_enough || promoted_bytes >= gc_num .interval ) &&
3156
- (promoted_bytes >= default_collect_interval || prev_sweep_full )) ||
3157
- grown_heap_age > 1 ) && gc_num .pause > 1 ) {
3158
- sweep_full = 1 ;
3169
+
3170
+ if (not_freed_enough ) {
3171
+ gc_num .interval = gc_num .interval * 2 ;
3159
3172
}
3160
- // update heuristics only if this GC was automatically triggered
3161
- if (collection == JL_GC_AUTO ) {
3162
- if (sweep_full ) {
3163
- if (large_frontier )
3164
- gc_num .interval = last_long_collect_interval ;
3165
- if (not_freed_enough || large_frontier ) {
3166
- if (gc_num .interval <= 2 * (max_collect_interval /5 )) {
3167
- gc_num .interval = 5 * (gc_num .interval / 2 );
3168
- }
3169
- }
3170
- last_long_collect_interval = gc_num .interval ;
3171
- }
3172
- else {
3173
- // reset interval to default, or at least half of live_bytes
3174
- int64_t half = live_bytes /2 ;
3175
- if (default_collect_interval < half && half <= max_collect_interval )
3176
- gc_num .interval = half ;
3177
- else
3178
- gc_num .interval = default_collect_interval ;
3179
- }
3173
+
3174
+ if (large_frontier ) {
3175
+ sweep_full = 1 ;
3176
+ }
3177
+
3178
+ if (gc_num .interval > max_collect_interval ) {
3179
+
3180
+ if (not_freed_enough )
3181
+ sweep_full = 1 ;
3182
+
3183
+ gc_num .interval = max_collect_interval ;
3180
3184
}
3185
+
3186
+
3187
+ // update heuristics only if this GC was automatically triggered
3181
3188
if (gc_sweep_always_full ) {
3182
3189
sweep_full = 1 ;
3183
3190
}
@@ -3248,10 +3255,20 @@ static int _jl_gc_collect(jl_ptls_t ptls, jl_gc_collection_t collection)
3248
3255
gc_num .allocd = 0 ;
3249
3256
last_live_bytes = live_bytes ;
3250
3257
live_bytes += - gc_num .freed + gc_num .since_sweep ;
3258
+
3259
+ // If the current interval is larger than half the live data decrease the interval
3260
+ int64_t half = live_bytes /2 ;
3261
+ if (gc_num .interval > half ) gc_num .interval = half ;
3262
+ // But never go below default
3263
+ if (gc_num .interval < default_collect_interval ) gc_num .interval = default_collect_interval ;
3264
+
3265
+ gc_time_summary (sweep_full , t_start , gc_end_t , gc_num .freed , live_bytes , gc_num .interval , pause );
3266
+
3251
3267
if (prev_sweep_full ) {
3252
3268
last_full_live = live_bytes ;
3253
3269
grown_heap_age = 0 ;
3254
3270
}
3271
+
3255
3272
prev_sweep_full = sweep_full ;
3256
3273
gc_num .pause += !recollect ;
3257
3274
gc_num .total_time += pause ;
@@ -3390,6 +3407,7 @@ void jl_init_thread_heap(jl_ptls_t ptls)
3390
3407
jl_atomic_store_relaxed (& ptls -> gc_num .allocd , - (int64_t )gc_num .interval );
3391
3408
}
3392
3409
3410
+
3393
3411
// System-wide initializations
3394
3412
void jl_gc_init (void )
3395
3413
{
@@ -3406,6 +3424,7 @@ void jl_gc_init(void)
3406
3424
gc_num .interval = default_collect_interval ;
3407
3425
last_long_collect_interval = default_collect_interval ;
3408
3426
gc_num .allocd = 0 ;
3427
+ t_start = jl_hrtime ();
3409
3428
3410
3429
#ifdef _P64
3411
3430
// on a big memory machine, set max_collect_interval to totalmem / ncores / 2
@@ -3419,6 +3438,7 @@ void jl_gc_init(void)
3419
3438
#endif
3420
3439
jl_gc_mark_sp_t sp = {NULL , NULL , NULL , NULL };
3421
3440
gc_mark_loop (NULL , sp );
3441
+ t_start = jl_hrtime ();
3422
3442
}
3423
3443
3424
3444
// callback for passing OOM errors from gmp
0 commit comments