[commit: ghc] master: Don't get a new nursery if we exceeded large_alloc_lim (75fd5dc)

git at git.haskell.org git at git.haskell.org
Wed Jul 15 13:58:47 UTC 2015


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/75fd5dc204fb6bb9014f6bba4d680facbc952faf/ghc

>---------------------------------------------------------------

commit 75fd5dc204fb6bb9014f6bba4d680facbc952faf
Author: Simon Marlow <marlowsd at gmail.com>
Date:   Wed Jul 15 13:07:35 2015 +0100

    Don't get a new nursery if we exceeded large_alloc_lim
    
    Summary:
    When using nursery chunks, if we failed a heap check due to
    large_alloc_lim, we would pointlessly keep grabbing new nursery
    chunks when we should just GC immediately.
    
    Test Plan: validate
    
    Reviewers: austin, bgamari, niteria
    
    Subscribers: thomie
    
    Differential Revision: https://phabricator.haskell.org/D1072


>---------------------------------------------------------------

75fd5dc204fb6bb9014f6bba4d680facbc952faf
 rts/Schedule.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/rts/Schedule.c b/rts/Schedule.c
index f1e95bf..257e39a 100644
--- a/rts/Schedule.c
+++ b/rts/Schedule.c
@@ -1084,6 +1084,17 @@ schedulePostRunThread (Capability *cap, StgTSO *t)
 static rtsBool
 scheduleHandleHeapOverflow( Capability *cap, StgTSO *t )
 {
+    if (cap->r.rHpLim == NULL || cap->context_switch) {
+        // Sometimes we miss a context switch, e.g. when calling
+        // primitives in a tight loop, MAYBE_GC() doesn't check the
+        // context switch flag, and we end up waiting for a GC.
+        // See #1984, and concurrent/should_run/1984
+        cap->context_switch = 0;
+        appendToRunQueue(cap,t);
+    } else {
+        pushOnRunQueue(cap,t);
+    }
+
     // did the task ask for a large block?
     if (cap->r.rHpAlloc > BLOCK_SIZE) {
         // if so, get one and push it on the front of the nursery.
@@ -1141,27 +1152,23 @@ scheduleHandleHeapOverflow( Capability *cap, StgTSO *t )
             // run queue before us and steal the large block, but in that
             // case the thread will just end up requesting another large
             // block.
-            pushOnRunQueue(cap,t);
             return rtsFalse;  /* not actually GC'ing */
         }
     }
 
+    // if we got here because we exceeded large_alloc_lim, then
+    // proceed straight to GC.
+    if (g0->n_new_large_words >= large_alloc_lim) {
+        return rtsTrue;
+    }
+
+    // Otherwise, we just ran out of space in the current nursery.
+    // Grab another nursery if we can.
     if (getNewNursery(cap)) {
         debugTrace(DEBUG_sched, "thread %ld got a new nursery", t->id);
-        pushOnRunQueue(cap,t);
         return rtsFalse;
     }
 
-    if (cap->r.rHpLim == NULL || cap->context_switch) {
-        // Sometimes we miss a context switch, e.g. when calling
-        // primitives in a tight loop, MAYBE_GC() doesn't check the
-        // context switch flag, and we end up waiting for a GC.
-        // See #1984, and concurrent/should_run/1984
-        cap->context_switch = 0;
-        appendToRunQueue(cap,t);
-    } else {
-        pushOnRunQueue(cap,t);
-    }
     return rtsTrue;
     /* actual GC is done at the end of the while loop in schedule() */
 }



More information about the ghc-commits mailing list