void gc_gen_stats_verbose(GC_Gen* gc) { GC_Gen_Stats* stats = gc->stats; Boolean is_los_collected = stats->is_los_collected; if (collect_is_minor()){ TRACE2("gc.space", "GC: NOS Collection stats: " <<"\nGC: " << (gc_is_gen_mode()?"generational":"nongenerational") <<"\nGC: collection algo: " << (minor_is_semispace()?"semi-space":"partial-forward") <<"\nGC: num surviving objs: " << stats->nos_surviving_obj_num_minor <<"\nGC: size surviving objs: " << verbose_print_size(stats->nos_surviving_obj_size_minor) <<"\nGC: surviving ratio: " << (int)(stats->nos_surviving_ratio_minor*100) << "%\n"); }else{ TRACE2("gc.space", "GC: MOS Collection stats: " <<"\nGC: collection algo: " << (major_is_marksweep()?"mark-sweep":"slide compact") <<"\nGC: num surviving objs: "<<stats->nos_mos_suviving_obj_num_major <<"\nGC: size surviving objs: "<<verbose_print_size(stats->nos_mos_suviving_obj_size_major) <<"\nGC: surviving ratio: "<<(int)(stats->nos_mos_suviving_ratio_major*100)<<"%\n"); } if(stats->is_los_collected) { /*if los is collected, need to output los related info*/ TRACE2("gc.space", "GC: Lspace Collection stats: " <<"\nGC: collection algo: "<<(collect_is_major()?"slide compact":"mark sweep") <<"\nGC: num surviving objs: "<<stats->los_suviving_obj_num <<"\nGC: size surviving objs: "<<verbose_print_size(stats->los_suviving_obj_size) <<"\nGC: surviving ratio: "<<(int)(stats->los_surviving_ratio*100)<<"%\n"); } }
void gc_space_tuner_reset(GC* gc) { Space_Tuner* tuner = gc->tuner; if( collect_is_major()){ /*Clear the fields every major collection except the wast area statistic.*/ tuner->tuning_size = 0; tuner->interim_blocks = NULL; tuner->need_tune = FALSE; tuner->force_tune = FALSE; tuner->last_speed_los = tuner->speed_los; tuner->last_speed_mos = tuner->speed_mos; tuner->last_speed_nos = tuner->speed_nos; tuner->speed_los = 0; tuner->speed_mos = 0; tuner->speed_nos = 0; tuner->current_dw = 0; tuner->current_ds = 0; tuner->threshold_waste = 0; tuner->min_tuning_size = 0; /*Reset the sum up of wast area size only if los is changed.*/ if(tuner->kind != TRANS_NOTHING){ tuner->wast_los = 0; tuner->wast_mos = 0; } tuner->kind = TRANS_NOTHING; tuner->reverse = 0; } return; }
void wspace_decide_compaction_need(Wspace *wspace) { POINTER_SIZE_INT free_mem_size = free_mem_in_wspace(wspace, FALSE); float free_mem_ratio = (float)free_mem_size / wspace->committed_heap_size; #ifdef USE_UNIQUE_MARK_SWEEP_GC if( gc_con_is_in_STW(wspace->gc) && (free_mem_ratio > WSPACE_COMPACT_RATIO) && (wspace->gc->cause != GC_CAUSE_RUNTIME_FORCE_GC)){ #else if(collect_is_major()){ #endif wspace->need_compact = wspace->move_object = TRUE; } else { wspace->need_compact = wspace->move_object = FALSE; } } static inline void sorted_chunk_bucket_add_entry(Chunk_Header **head, Chunk_Header **tail, Chunk_Header *chunk) { chunk->prev = NULL; /* Field adj_prev is used as prev */ if(!*head){ assert(!*tail); chunk->next = NULL; *head = *tail = chunk; return; } assert(*tail); chunk->next = *head; (*head)->prev = chunk; *head = chunk; }
void gc_gen_mode_adapt(GC_Gen* gc, int64 pause_time) { if(GEN_NONGEN_SWITCH == FALSE) return; Blocked_Space* nos = (Blocked_Space*)gc->nos; Blocked_Space* mos = (Blocked_Space*)gc->mos; Gen_Mode_Adaptor* gen_mode_adaptor = gc->gen_mode_adaptor; POINTER_SIZE_INT mos_free_size = blocked_space_free_mem_size(mos); POINTER_SIZE_INT nos_free_size = blocked_space_free_mem_size(nos); POINTER_SIZE_INT total_free_size = mos_free_size + nos_free_size; if(collect_is_major()) { assert(!gc_is_gen_mode()); if(gen_mode_adaptor->major_survive_ratio_threshold != 0 && mos->survive_ratio > gen_mode_adaptor->major_survive_ratio_threshold){ if(gen_mode_adaptor->major_repeat_count > MAX_MAJOR_REPEAT_COUNT ){ gc->force_gen_mode = TRUE; gc_set_gen_mode(TRUE); gc->next_collect_force_major = FALSE; return; }else{ gen_mode_adaptor->major_repeat_count++; } }else{ gen_mode_adaptor->major_repeat_count = 1; } }else{ /*compute throughput*/ if(!collect_last_is_minor((GC*)gc)){ gen_mode_adaptor->nongen_minor_throughput = 1.0f; } if(gc->force_gen_mode){ if(pause_time!=0){ if(gen_mode_adaptor->gen_minor_throughput != 0) gen_mode_adaptor->gen_minor_throughput = (gen_mode_adaptor->gen_minor_throughput + (float) nos_free_size/(float)pause_time)/2.0f; else gen_mode_adaptor->gen_minor_throughput =(float) nos_free_size/(float)pause_time; } }else{ if(pause_time!=0){ if(gen_mode_adaptor->gen_minor_throughput != 1.0f) gen_mode_adaptor->nongen_minor_throughput = (gen_mode_adaptor->nongen_minor_throughput + (float) nos_free_size/(float)pause_time)/2.0f; else gen_mode_adaptor->nongen_minor_throughput = (float) nos_free_size/(float)pause_time; } } if(gen_mode_adaptor->nongen_minor_throughput <= gen_mode_adaptor->gen_minor_throughput ){ if( !collect_last_is_minor((GC*)gc) ){ gen_mode_adaptor->major_survive_ratio_threshold = mos->survive_ratio; }else if( !gc->force_gen_mode ){ gc->force_gen_mode = TRUE; gen_mode_adaptor->gen_mode_trial_count = MAX_INT32; } } if(gc->next_collect_force_major && !gc->force_gen_mode){ gc->next_collect_force_major = FALSE; gc->force_gen_mode = TRUE; gen_mode_adaptor->gen_mode_trial_count = 2; }else if( collect_last_is_minor((GC*)gc) && gc->force_gen_mode){ gen_mode_adaptor->gen_mode_trial_count = MAX_INT32; } if(gc->force_gen_mode && (total_free_size <= ((float)min_nos_size_bytes) * 1.3 )){ gc->force_gen_mode = FALSE; gc_set_gen_mode(FALSE); gc->next_collect_force_major = TRUE; gen_mode_adaptor->gen_mode_trial_count = 0; return; } if( gc->force_gen_mode ){ assert( gen_mode_adaptor->gen_mode_trial_count >= 0); gen_mode_adaptor->gen_mode_trial_count --; if( gen_mode_adaptor->gen_mode_trial_count >= 0){ gc_set_gen_mode(TRUE); return; } gc->force_gen_mode = FALSE; gc->next_collect_force_major = TRUE; gen_mode_adaptor->gen_mode_trial_count = 0; } } gc_set_gen_mode(FALSE); return; }
static void gc_decide_next_collect(GC_Gen* gc, int64 pause_time) { Space* nos = (Space*)gc->nos; Space* mos = (Space*)gc->mos; float survive_ratio = 0.2f; if( MOS_RESERVE_SIZE != 0) DEFAULT_MOS_RESERVE_SIZE = MOS_RESERVE_SIZE; POINTER_SIZE_INT mos_free_size = mos_free_space_size(mos); /* for space free size computation, semispace may leave some nos space used. But we use a simple approximation here. That is, we just use the totoal nos size as nos free size. This is important. We can't use real nos_free_space_size(), because the whole algorithm here in gc_decide_next_collect() assumes total free size is reduced after every minor collection, and can only be increased after major collection. Otherwise the algorithm is invalid. If we use nos_free_space_size(), we may get an increased total free size after a minor collection. */ POINTER_SIZE_INT nos_free_size = space_committed_size(nos); POINTER_SIZE_INT total_free_size = mos_free_size + nos_free_size; if(collect_is_major()) gc->force_gen_mode = FALSE; if(!gc->force_gen_mode){ /*Major collection:*/ if(collect_is_major()){ mos->time_collections += pause_time; Tslow = (float)pause_time; SMax = total_free_size; /*If fall back happens, and nos_boundary reaches heap_ceiling, then we force major.*/ if( nos_free_size == 0) gc->next_collect_force_major = TRUE; else gc->next_collect_force_major = FALSE; /*If major is caused by LOS, or collection kind is ALGO_MAJOR_EXTEND, all survive ratio is not updated.*/ extern Boolean mos_extended; if((gc->cause != GC_CAUSE_LOS_IS_FULL) && !mos_extended ){ survive_ratio = (float)mos->period_surviving_size/(float)mos->committed_heap_size; mos->survive_ratio = survive_ratio; } /* why do I set it FALSE here? because here is the only place where it's used. */ mos_extended = FALSE; /*If there is no minor collection at all, we must give mos expected threshold a reasonable value.*/ if((gc->tuner->kind != TRANS_NOTHING) && (nos->num_collections == 0)) mspace_set_expected_threshold_ratio((Mspace *)mos, 0.5f); /*If this major is caused by fall back compaction, we must give nos->survive_ratio *a conservative and reasonable number to avoid next fall back. *In fallback compaction, the survive_ratio of mos must be 1.*/ if(collect_is_fallback()) nos->survive_ratio = 1; } /*Minor collection:*/ else { /*Give a hint to mini_free_ratio. */ if(nos->num_collections == 1){ /*Fixme: This is only set for tuning the first warehouse!*/ Tslow = pause_time / gc->survive_ratio; SMax = (POINTER_SIZE_INT)((float)(gc->committed_heap_size - gc->los->committed_heap_size) * ( 1 - gc->survive_ratio )); last_total_free_size = gc->committed_heap_size - gc->los->committed_heap_size; } nos->time_collections += pause_time; POINTER_SIZE_INT free_size_threshold; POINTER_SIZE_INT minor_surviving_size = last_total_free_size - total_free_size; /*If the first GC is caused by LOS, mos->last_alloced_size should be smaller than this minor_surviving_size *Because the last_total_free_size is not accurate.*/ if(nos->num_collections != 1){ assert(minor_surviving_size == mos->last_alloced_size); } float k = Tslow * nos->num_collections/nos->time_collections; float m = ((float)minor_surviving_size)*1.0f/((float)(SMax - DEFAULT_MOS_RESERVE_SIZE )); float free_ratio_threshold = mini_free_ratio(k, m); if(SMax > DEFAULT_MOS_RESERVE_SIZE ) free_size_threshold = (POINTER_SIZE_INT)(free_ratio_threshold * (SMax - DEFAULT_MOS_RESERVE_SIZE ) + DEFAULT_MOS_RESERVE_SIZE ); else free_size_threshold = (POINTER_SIZE_INT)(free_ratio_threshold * SMax); /* FIXME: if the total free size is lesser than threshold, the time point might be too late! * Have a try to test whether the backup solution is better for specjbb. */ // if ((mos_free_size + nos_free_size + minor_surviving_size) < free_size_threshold) gc->next_collect_force_major = TRUE; if ((mos_free_size + nos_free_size)< free_size_threshold) gc->next_collect_force_major = TRUE; survive_ratio = (float)minor_surviving_size/(float)space_committed_size((Space*)nos); nos->survive_ratio = survive_ratio; /*For LOS_Adaptive*/ POINTER_SIZE_INT mos_committed_size = space_committed_size((Space*)mos); POINTER_SIZE_INT nos_committed_size = space_committed_size((Space*)nos); if(mos_committed_size + nos_committed_size > free_size_threshold){ POINTER_SIZE_INT mos_size_threshold; mos_size_threshold = mos_committed_size + nos_committed_size - free_size_threshold; float mos_size_threshold_ratio = (float)mos_size_threshold / (mos_committed_size + nos_committed_size); mspace_set_expected_threshold_ratio((Mspace *)mos, mos_size_threshold_ratio); } } gc->survive_ratio = (gc->survive_ratio + survive_ratio)/2.0f; last_total_free_size = total_free_size; } gc_gen_mode_adapt(gc,pause_time); return; }