diff options
author | Simon Marlow <marlowsd@gmail.com> | 2014-11-21 17:05:58 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2014-11-25 14:37:26 +0000 |
commit | 452eb80f15fce8665df52bc9facebfafb5b6267b (patch) | |
tree | a34e76ab765b6d1db49b1c05372f8924e52cacf9 /rts/sm/Storage.c | |
parent | e22bc0dedb9e9da0176ad7ce4a74acbefedc7207 (diff) | |
download | haskell-452eb80f15fce8665df52bc9facebfafb5b6267b.tar.gz |
Add +RTS -n<size>: divide the nursery into chunks
See the documentation for details.
Diffstat (limited to 'rts/sm/Storage.c')
-rw-r--r-- | rts/sm/Storage.c | 117 |
1 files changed, 89 insertions, 28 deletions
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c index e4a6984c40..f02c00591c 100644 --- a/rts/sm/Storage.c +++ b/rts/sm/Storage.c @@ -55,6 +55,8 @@ generation *g0 = NULL; /* generation 0, for convenience */ generation *oldest_gen = NULL; /* oldest generation, for convenience */ nursery *nurseries = NULL; /* array of nurseries, size == n_capabilities */ +nat n_nurseries; +volatile StgWord next_nursery = 0; #ifdef THREADED_RTS /* @@ -65,6 +67,7 @@ Mutex sm_mutex; #endif static void allocNurseries (nat from, nat to); +static void assignNurseriesToCapabilities (nat from, nat to); static void initGeneration (generation *gen, int g) @@ -190,6 +193,7 @@ initStorage (void) N = 0; + next_nursery = 0; storageAddCapabilities(0, n_capabilities); IF_DEBUG(gc, statDescribeGens()); @@ -206,13 +210,22 @@ initStorage (void) void storageAddCapabilities (nat from, nat to) { - nat n, g, i; + nat n, g, i, new_n_nurseries; + + if (RtsFlags.GcFlags.nurseryChunkSize == 0) { + new_n_nurseries = to; + } else { + memcount total_alloc = to * RtsFlags.GcFlags.minAllocAreaSize; + new_n_nurseries = + stg_max(to, total_alloc / RtsFlags.GcFlags.nurseryChunkSize); + } if (from > 0) { - nurseries = stgReallocBytes(nurseries, to * sizeof(struct nursery_), + nurseries = stgReallocBytes(nurseries, + new_n_nurseries * sizeof(struct nursery_), "storageAddCapabilities"); } else { - nurseries = stgMallocBytes(to * sizeof(struct nursery_), + nurseries = stgMallocBytes(new_n_nurseries * sizeof(struct nursery_), "storageAddCapabilities"); } @@ -228,7 +241,15 @@ void storageAddCapabilities (nat from, nat to) * don't want it to be a big one. This vague idea is borne out by * rigorous experimental evidence. */ - allocNurseries(from, to); + allocNurseries(n_nurseries, new_n_nurseries); + n_nurseries = new_n_nurseries; + + /* + * Assign each of the new capabilities a nursery. Remember to start from + * next_nursery, because we may have already consumed some of the earlier + * nurseries. + */ + assignNurseriesToCapabilities(from,to); // allocate a block for each mut list for (n = from; n < to; n++) { @@ -525,15 +546,26 @@ allocNursery (bdescr *tail, W_ blocks) return &bd[0]; } +STATIC_INLINE void +assignNurseryToCapability (Capability *cap, nat n) +{ + cap->r.rNursery = &nurseries[n]; + cap->r.rCurrentNursery = nurseries[n].blocks; + newNurseryBlock(nurseries[n].blocks); + cap->r.rCurrentAlloc = NULL; +} + +/* + * Give each Capability a nursery from the pool. No need to do atomic increments + * here, everything must be stopped to call this function. + */ static void assignNurseriesToCapabilities (nat from, nat to) { nat i; for (i = from; i < to; i++) { - capabilities[i]->r.rCurrentNursery = nurseries[i].blocks; - newNurseryBlock(nurseries[i].blocks); - capabilities[i]->r.rCurrentAlloc = NULL; + assignNurseryToCapability(capabilities[i], next_nursery++); } } @@ -541,42 +573,46 @@ static void allocNurseries (nat from, nat to) { nat i; + memcount n_blocks; + + if (RtsFlags.GcFlags.nurseryChunkSize) { + n_blocks = RtsFlags.GcFlags.nurseryChunkSize; + } else { + n_blocks = RtsFlags.GcFlags.minAllocAreaSize; + } for (i = from; i < to; i++) { - nurseries[i].blocks = - allocNursery(NULL, RtsFlags.GcFlags.minAllocAreaSize); - nurseries[i].n_blocks = - RtsFlags.GcFlags.minAllocAreaSize; + nurseries[i].blocks = allocNursery(NULL, n_blocks); + nurseries[i].n_blocks = n_blocks; } - assignNurseriesToCapabilities(from, to); } void -clearNursery (Capability *cap USED_IF_DEBUG) +resetNurseries (void) { + next_nursery = 0; + assignNurseriesToCapabilities(0, n_capabilities); + #ifdef DEBUG bdescr *bd; - for (bd = nurseries[cap->no].blocks; bd; bd = bd->link) { - ASSERT(bd->gen_no == 0); - ASSERT(bd->gen == g0); - IF_DEBUG(sanity, memset(bd->start, 0xaa, BLOCK_SIZE)); + nat n; + for (n = 0; n < n_nurseries; n++) { + for (bd = nurseries[n].blocks; bd; bd = bd->link) { + ASSERT(bd->gen_no == 0); + ASSERT(bd->gen == g0); + IF_DEBUG(sanity, memset(bd->start, 0xaa, BLOCK_SIZE)); + } } #endif } -void -resetNurseries (void) -{ - assignNurseriesToCapabilities(0, n_capabilities); -} - W_ countNurseryBlocks (void) { nat i; W_ blocks = 0; - for (i = 0; i < n_capabilities; i++) { + for (i = 0; i < n_nurseries; i++) { blocks += nurseries[i].n_blocks; } return blocks; @@ -625,15 +661,30 @@ resizeNursery (nursery *nursery, W_ blocks) // // Resize each of the nurseries to the specified size. // -void -resizeNurseriesFixed (W_ blocks) +static void +resizeNurseriesEach (W_ blocks) { nat i; - for (i = 0; i < n_capabilities; i++) { + + for (i = 0; i < n_nurseries; i++) { resizeNursery(&nurseries[i], blocks); } } +void +resizeNurseriesFixed (void) +{ + nat blocks; + + if (RtsFlags.GcFlags.nurseryChunkSize) { + blocks = RtsFlags.GcFlags.nurseryChunkSize; + } else { + blocks = RtsFlags.GcFlags.minAllocAreaSize; + } + + resizeNurseriesEach(blocks); +} + // // Resize the nurseries to the total specified size. // @@ -642,9 +693,19 @@ resizeNurseries (W_ blocks) { // If there are multiple nurseries, then we just divide the number // of available blocks between them. - resizeNurseriesFixed(blocks / n_capabilities); + resizeNurseriesEach(blocks / n_nurseries); } +rtsBool +getNewNursery (Capability *cap) +{ + StgWord i = atomic_inc(&next_nursery, 1) - 1; + if (i >= n_nurseries) { + return rtsFalse; + } + assignNurseryToCapability(cap, i); + return rtsTrue; +} /* ----------------------------------------------------------------------------- move_STACK is called to update the TSO structure after it has been |