- /* Two-space collector:
- * Free the old to-space, and estimate the amount of live data.
- */
- if (RtsFlags.GcFlags.generations == 1) {
- nat blocks;
-
- /* For a two-space collector, we need to resize the nursery. */
-
- /* set up a new nursery. Allocate a nursery size based on a
- * function of the amount of live data (by default a factor of 2)
- * Use the blocks from the old nursery if possible, freeing up any
- * left over blocks.
- *
- * If we get near the maximum heap size, then adjust our nursery
- * size accordingly. If the nursery is the same size as the live
- * data (L), then we need 3L bytes. We can reduce the size of the
- * nursery to bring the required memory down near 2L bytes.
- *
- * A normal 2-space collector would need 4L bytes to give the same
- * performance we get from 3L bytes, reducing to the same
- * performance at 2L bytes.
- */
- blocks = g0s0->n_blocks;
-
- if ( RtsFlags.GcFlags.maxHeapSize != 0 &&
- blocks * RtsFlags.GcFlags.oldGenFactor * 2 >
- RtsFlags.GcFlags.maxHeapSize ) {
- long adjusted_blocks; // signed on purpose
- int pc_free;
-
- adjusted_blocks = (RtsFlags.GcFlags.maxHeapSize - 2 * blocks);
-
- debugTrace(DEBUG_gc, "near maximum heap size of 0x%x blocks, blocks = %d, adjusted to %ld",
- RtsFlags.GcFlags.maxHeapSize, blocks, adjusted_blocks);
-
- pc_free = adjusted_blocks * 100 / RtsFlags.GcFlags.maxHeapSize;
- if (pc_free < RtsFlags.GcFlags.pcFreeHeap) /* might even be < 0 */ {
- heapOverflow();
- }
- blocks = adjusted_blocks;
-
- } else {
- blocks *= RtsFlags.GcFlags.oldGenFactor;
- if (blocks < RtsFlags.GcFlags.minAllocAreaSize) {
- blocks = RtsFlags.GcFlags.minAllocAreaSize;
- }
- }
- resizeNurseries(blocks);
-
- } else {
- /* Generational collector:
- * If the user has given us a suggested heap size, adjust our
- * allocation area to make best use of the memory available.
- */
-
- if (RtsFlags.GcFlags.heapSizeSuggestion) {
- long blocks;
- nat needed = calcNeeded(); // 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
- * percentage of g0s0 that was live at the last minor GC.
- */
- if (N == 0) {
- g0s0_pcnt_kept = (new_blocks * 100) / countNurseryBlocks();
- }
-
- /* Estimate a size for the allocation area based on the
- * information available. We might end up going slightly under
- * or over the suggested heap size, but we should be pretty
- * close on average.
- *
- * Formula: suggested - needed
- * ----------------------------
- * 1 + g0s0_pcnt_kept/100
- *
- * where 'needed' is the amount of memory needed at the next
- * collection for collecting all steps except g0s0.
- */
- blocks =
- (((long)RtsFlags.GcFlags.heapSizeSuggestion - (long)needed) * 100) /
- (100 + (long)g0s0_pcnt_kept);
-
- if (blocks < (long)RtsFlags.GcFlags.minAllocAreaSize) {
- blocks = RtsFlags.GcFlags.minAllocAreaSize;
- }
-
- resizeNurseries((nat)blocks);
-
- } else {
- // we might have added extra large blocks to the nursery, so
- // resize back to minAllocAreaSize again.
- resizeNurseriesFixed(RtsFlags.GcFlags.minAllocAreaSize);
- }
- }