pike.git / src / gc.c

version» Context lines:

pike.git/src/gc.c:89:    * gc pass will be freed. That's done before the live object destruct    * pass. Internal weak references are however still intact.    *    * Note: Keep the doc for lfun::destroy up-to-date with the above.    */      /* #define GC_DEBUG */   /* #define GC_VERBOSE */   /* #define GC_CYCLE_DEBUG */   /* #define GC_STACK_DEBUG */ + /* #define GC_INTERVAL_DEBUG */      #if defined(GC_VERBOSE) && !defined(PIKE_DEBUG)   #undef GC_VERBOSE   #endif   #ifdef GC_VERBOSE   #define GC_VERBOSE_DO(X) X   #else   #define GC_VERBOSE_DO(X)   #endif   
pike.git/src/gc.c:3431: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    unsigned obj_count;    ONERROR uwp;   #endif       if(Pike_in_gc) return 0;       if (gc_enabled <= 0 && (gc_enabled < 0 || !explicit_call)) {    num_allocs = 0;    alloc_threshold = GC_MAX_ALLOC_THRESHOLD; + #ifdef GC_INTERVAL_DEBUG +  fprintf (stderr, "GC disabled: num_allocs 0, alloc_threshold max\n"); + #endif    if (gc_evaluator_callback) {    remove_callback (gc_evaluator_callback);    gc_evaluator_callback = NULL;    }    return 0;    }      #ifdef DEBUG_MALLOC    if(debug_options & GC_RESET_DMALLOC)    reset_debug_malloc();
pike.git/src/gc.c:3877: Inside #if defined(PIKE_DEBUG)
   "Done searching for marker(s) with extra refs.\n");    Pike_fatal("Lost track of %d extra refs to things in gc.\n", gc_extra_refs);    }    if(fatal_after_gc) Pike_fatal("%s", fatal_after_gc);   #endif       /* Calculate the next alloc_threshold. */    {    double multiplier, new_threshold;    cpu_time_t last_non_gc_time, last_gc_time; + #ifdef GC_INTERVAL_DEBUG +  double tmp_dbl1, tmp_dbl2; + #endif       /* If we're at an automatic and timely gc then start_allocs ==    * alloc_threshold and we're using gc_average_slowness in the    * decaying average calculation. Otherwise this is either an    * explicit call (start_allocs < alloc_threshold) or the gc has    * been delayed past its due time (start_allocs >    * alloc_threshold), and in those cases we adjust the multiplier    * to give the appropriate weight to this last instance. */    multiplier=pow(gc_average_slowness,    (double) start_allocs / (double) alloc_threshold);    -  + #ifdef GC_INTERVAL_DEBUG +  if (GC_VERBOSE_DO(1 ||) gc_trace) fputc ('\n', stderr); +  fprintf (stderr, "IN: GC start @ %"PRINT_CPU_TIME" "CPU_TIME_UNIT"\n" +  " avg slow %g, start_allocs %"PRINT_ALLOC_COUNT_TYPE", " +  "alloc_threshold %"PRINT_ALLOC_COUNT_TYPE" -> mult %g\n", +  gc_start_real_time, +  gc_average_slowness, start_allocs, alloc_threshold, multiplier); +  tmp_dbl1 = non_gc_time; +  tmp_dbl2 = gc_time; + #endif +     /* Comparisons to avoid that overflows mess up the statistics. */    if (last_gc_end_real_time != -1 &&    gc_start_real_time > last_gc_end_real_time) {    last_non_gc_time = gc_start_real_time - last_gc_end_real_time;    non_gc_time = non_gc_time * multiplier +    last_non_gc_time * (1.0 - multiplier);    }    else last_non_gc_time = (cpu_time_t) -1;    last_gc_end_real_time = get_real_time();    if (last_gc_end_real_time > gc_start_real_time) {    gc_time = gc_time * multiplier +    (last_gc_end_real_time - gc_start_real_time) * (1.0 - multiplier);    } -  +  + #ifdef GC_INTERVAL_DEBUG +  fprintf (stderr, +  " non_gc_time: %13"PRINT_CPU_TIME" "CPU_TIME_UNIT", " +  "%.12g -> %.12g\n" +  " gc_time: %13"PRINT_CPU_TIME" "CPU_TIME_UNIT", " +  "%.12g -> %.12g\n", +  last_non_gc_time, tmp_dbl1, non_gc_time, +  last_gc_end_real_time > gc_start_real_time ? +  last_gc_end_real_time - gc_start_real_time : (cpu_time_t) -1, +  tmp_dbl2, gc_time); +  tmp_dbl1 = objects_alloced; +  tmp_dbl2 = objects_freed; + #endif +     {    cpu_time_t gc_end_time = get_cpu_time();    if (gc_end_time > gc_start_time)    last_gc_time = gc_end_time - gc_start_time;    else    last_gc_time = (cpu_time_t) -1;    }       /* At this point, unreferenced contains the number of things that    * were without external references during the check and mark
pike.git/src/gc.c:3923:    * Therefore we use that figure instead of the difference between    * the number of allocated things to measure the amount of    * garbage. */    last_garbage_ratio = (double) unreferenced / start_num_objs;       objects_alloced = objects_alloced * multiplier +    start_allocs * (1.0 - multiplier);    objects_freed = objects_freed * multiplier +    unreferenced * (1.0 - multiplier);    + #ifdef GC_INTERVAL_DEBUG +  fprintf (stderr, +  " objects_alloced: %9"PRINT_ALLOC_COUNT_TYPE" allocs, " +  "%.12g -> %.12g\n" +  " objects_freed: %9"PRINT_ALLOC_COUNT_TYPE" unrefd, " +  "%.12g -> %.12g\n", +  start_allocs, tmp_dbl1, objects_alloced, +  unreferenced, tmp_dbl2, objects_freed); + #endif +     if (last_non_gc_time == (cpu_time_t) -1 ||    gc_time / non_gc_time <= gc_time_ratio) {    /* Calculate the new threshold by adjusting the average    * threshold (objects_alloced) with the ratio between the wanted    * garbage at the next gc (gc_garbage_ratio_low *    * start_num_objs) and the actual average garbage    * (objects_freed). (Where the +1.0's come from I don't know.    * Perhaps they're to avoid division by zero. /mast) */    new_threshold = (objects_alloced+1.0) *    (gc_garbage_ratio_low * start_num_objs) / (objects_freed+1.0);    last_garbage_strategy = GARBAGE_RATIO_LOW; -  + #ifdef GC_INTERVAL_DEBUG +  fprintf (stderr, " strategy: low ratio %g, objs %"PRINTSIZET"u, " +  "new threshold -> %.12g\n", +  gc_garbage_ratio_low, start_num_objs, new_threshold); + #endif    }    else {    new_threshold = (objects_alloced+1.0) *    (gc_garbage_ratio_high * start_num_objs) / (objects_freed+1.0);    last_garbage_strategy = GARBAGE_RATIO_HIGH; -  + #ifdef GC_INTERVAL_DEBUG +  fprintf (stderr, " strategy: high ratio %g, objs %"PRINTSIZET"u, " +  "new threshold -> %.12g\n", +  gc_garbage_ratio_high, start_num_objs, new_threshold); + #endif    }       if (non_gc_time > 0.0 && gc_min_time_ratio > 0.0) {    /* Upper limit on the new threshold based on gc_min_time_ratio. */    double max_threshold = (objects_alloced+1.0) *    gc_time / (gc_min_time_ratio * non_gc_time);    if (max_threshold < new_threshold) {    new_threshold = max_threshold;    last_garbage_strategy = GARBAGE_MAX_INTERVAL;    } -  + #ifdef GC_INTERVAL_DEBUG +  fprintf (stderr, " max interval? min time ratio %g, " +  "max threshold %.12g -> %s\n", +  gc_min_time_ratio, max_threshold, +  max_threshold < new_threshold ? "yes" : "no"); + #endif    }      #if 0    /* Afaics this is to limit the growth of the threshold to avoid    * that a single sudden allocation spike causes a very long gc    * interval the next time. Now when the bug in the decaying    * average calculation is fixed there should be no risk for that,    * at least not in any case when this would help. /mast */    if(alloc_threshold + start_allocs < new_threshold)    new_threshold = (double)(alloc_threshold + start_allocs);   #endif       if(new_threshold < GC_MIN_ALLOC_THRESHOLD)    alloc_threshold = GC_MIN_ALLOC_THRESHOLD;    else if(new_threshold > GC_MAX_ALLOC_THRESHOLD)    alloc_threshold = GC_MAX_ALLOC_THRESHOLD;    else    alloc_threshold = (ALLOC_COUNT_TYPE) new_threshold;    -  + #ifdef GC_INTERVAL_DEBUG +  fprintf (stderr, "OUT: GC end @ %"PRINT_CPU_TIME" "CPU_TIME_UNIT", " +  "new capped threshold %"PRINT_ALLOC_COUNT_TYPE"\n", +  last_gc_end_real_time, alloc_threshold); + #endif +     if (!explicit_call) {    auto_gc_real_time += get_real_time() - gc_start_real_time;       if (last_gc_time != (cpu_time_t) -1) {   #ifdef CPU_TIME_MIGHT_BE_THREAD_LOCAL    if (cpu_time_is_thread_local   #ifdef PIKE_DEBUG    /* At high debug levels, the gc may get called before    * the threads are initialized.    */