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");
  }

}
Exemple #2
0
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;  
  
}
Exemple #3
0
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;
}