Commit bbb5843b authored by Simon Marlow's avatar Simon Marlow
Browse files

Fix a discrepancy between two calculations of which generation to collect

The calculation should be done in one place, of course.
parent bb120dfd
......@@ -137,7 +137,6 @@ DECLARE_GCT
static void mark_root (void *user, StgClosure **root);
static void zero_static_object_list (StgClosure* first_static);
static nat initialise_N (rtsBool force_major_gc);
static void prepare_collected_gen (generation *gen);
static void prepare_uncollected_gen (generation *gen);
static void init_gc_thread (gc_thread *t);
......@@ -235,7 +234,8 @@ GarbageCollect (rtsBool force_major_gc,
/* Figure out which generation to collect
*/
n = initialise_N(force_major_gc);
N = calcNeeded(force_major_gc, NULL);
major_gc = (N == RtsFlags.GcFlags.generations-1);
#if defined(THREADED_RTS)
work_stealing = RtsFlags.ParFlags.parGcLoadBalancingEnabled &&
......@@ -269,8 +269,8 @@ GarbageCollect (rtsBool force_major_gc,
n_gc_threads = 1;
#endif
debugTrace(DEBUG_gc, "GC (gen %d): %d KB to collect, %ld MB in use, using %d thread(s)",
N, n * (BLOCK_SIZE / 1024), mblocks_allocated, n_gc_threads);
debugTrace(DEBUG_gc, "GC (gen %d, using %d thread(s))",
N, n_gc_threads);
#ifdef RTS_GTK_FRONTPANEL
if (RtsFlags.GcFlags.frontpanel) {
......@@ -752,7 +752,7 @@ GarbageCollect (rtsBool force_major_gc,
N, n_gc_threads, par_max_copied, par_tot_copied);
// Guess which generation we'll collect *next* time
initialise_N(force_major_gc);
N = calcNeeded(force_major_gc, NULL);
#if defined(RTS_USER_SIGNALS)
if (RtsFlags.MiscFlags.install_signal_handlers) {
......@@ -766,47 +766,6 @@ GarbageCollect (rtsBool force_major_gc,
SET_GCT(saved_gct);
}
/* -----------------------------------------------------------------------------
Figure out which generation to collect, initialise N and major_gc.
Also returns the total number of blocks in generations that will be
collected.
-------------------------------------------------------------------------- */
static nat
initialise_N (rtsBool force_major_gc)
{
int g;
nat blocks, blocks_total;
blocks = 0;
blocks_total = 0;
if (force_major_gc) {
N = RtsFlags.GcFlags.generations - 1;
} else {
N = 0;
}
for (g = RtsFlags.GcFlags.generations - 1; g >= 0; g--) {
blocks = generations[g].n_words / BLOCK_SIZE_W
+ generations[g].n_large_blocks;
if (blocks >= generations[g].max_blocks) {
N = stg_max(N,g);
}
if ((nat)g <= N) {
blocks_total += blocks;
}
}
blocks_total += countNurseryBlocks();
major_gc = (N == RtsFlags.GcFlags.generations-1);
return blocks_total;
}
/* -----------------------------------------------------------------------------
Initialise the gc_thread structures.
-------------------------------------------------------------------------- */
......@@ -1702,7 +1661,9 @@ resize_nursery (void)
if (RtsFlags.GcFlags.heapSizeSuggestion)
{
long blocks;
const nat needed = calcNeeded(); // approx blocks needed at next GC
lnat needed;
calcNeeded(rtsFalse, &needed); // approx blocks needed at next GC
/* Guess how much will be live in generation 0 step 0 next time.
* A good approximation is obtained by finding the
......@@ -1725,7 +1686,7 @@ resize_nursery (void)
* close on average.
*
* Formula: suggested - needed
* ----------------------------
* ----------------------------
* 1 + g0_pcnt_kept/100
*
* where 'needed' is the amount of memory needed at the next
......
......@@ -1003,29 +1003,44 @@ lnat calcLiveBlocks (void)
return live;
}
/* Approximate the number of blocks that will be needed at the next
* garbage collection.
/* Determine which generation will be collected next, and approximate
* the maximum amount of memory that will be required to do the GC,
* taking into account data that will be copied, and the space needed
* to store bitmaps and the mark stack. Note: blocks_needed does not
* include the blocks in the nursery.
*
* Assume: all data currently live will remain live. Generationss
* that will be collected next time will therefore need twice as many
* blocks since all the data will be copied.
*/
extern lnat
calcNeeded(void)
calcNeeded (rtsBool force_major, lnat *blocks_needed)
{
lnat needed = 0;
nat g;
lnat needed = 0, blocks;
nat g, N;
generation *gen;
if (force_major) {
N = RtsFlags.GcFlags.generations - 1;
} else {
N = 0;
}
for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
gen = &generations[g];
blocks = gen->n_blocks // or: gen->n_words / BLOCK_SIZE_W (?)
+ gen->n_large_blocks;
// we need at least this much space
needed += gen->n_blocks + gen->n_large_blocks;
needed += blocks;
// any additional space needed to collect this gen next time?
// are we collecting this gen?
if (g == 0 || // always collect gen 0
(gen->n_blocks + gen->n_large_blocks > gen->max_blocks)) {
blocks > gen->max_blocks)
{
N = stg_max(N,g);
// we will collect this gen next time
if (gen->mark) {
// bitmap:
......@@ -1040,7 +1055,11 @@ calcNeeded(void)
}
}
}
return needed;
if (blocks_needed != NULL) {
*blocks_needed = needed;
}
return N;
}
/* ----------------------------------------------------------------------------
......
......@@ -92,8 +92,8 @@ lnat countNurseryBlocks ( void );
lnat updateNurseriesStats (void);
lnat countLargeAllocated (void);
lnat countOccupied (bdescr *bd);
lnat calcNeeded (void);
lnat countOccupied (bdescr *bd);
lnat calcNeeded (rtsBool force_major, lnat *blocks_needed);
lnat gcThreadLiveWords (nat i, nat g);
lnat gcThreadLiveBlocks (nat i, nat g);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment