[pypy-commit] pypy gc-incminimark-pinning-countlimit: simple implementation and tests for limiting the amount of pinned objects

groggi noreply at buildbot.pypy.org
Mon Jun 2 17:24:47 CEST 2014


Author: Gregor Wegberg <code at gregorwegberg.com>
Branch: gc-incminimark-pinning-countlimit
Changeset: r71858:345cfc1ac23a
Date: 2014-05-29 20:02 +0200
http://bitbucket.org/pypy/pypy/changeset/345cfc1ac23a/

Log:	simple implementation and tests for limiting the amount of pinned
	objects

diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -256,6 +256,10 @@
         # so we trade it by cleaning it bit-by-bit, as we progress through
         # nursery. Has to fit at least one large object
         "nursery_cleanup": 32768 * WORD,
+
+        # Number of  objects that are allowed to be pinned in the nursery
+        # at the same time.
+        "max_number_of_pinned_objects": 100,
         }
 
     def __init__(self, config,
@@ -268,6 +272,7 @@
                  major_collection_threshold=2.5,
                  growth_rate_max=2.5,   # for tests
                  card_page_indices=0,
+                 max_number_of_pinned_objects=100,
                  large_object=8*WORD,
                  ArenaCollectionClass=None,
                  **kwds):
@@ -284,6 +289,7 @@
         self.max_heap_size = 0.0
         self.max_heap_size_already_raised = False
         self.max_delta = float(r_uint(-1))
+        self.max_number_of_pinned_objects = max_number_of_pinned_objects
         #
         self.card_page_indices = card_page_indices
         if self.card_page_indices > 0:
@@ -965,7 +971,7 @@
             # Reason: It would be possible that the first caller unpins
             # while the second caller thinks it's still pinned.
             return False
-        if not self.should_pin(obj):
+        if self.pinned_objects_in_nursery >= self.max_number_of_pinned_objects:
             return False
 
         self.header(obj).tid |= GCFLAG_PINNED
@@ -981,9 +987,6 @@
         self.header(obj).tid &= ~GCFLAG_PINNED
         self.pinned_objects_in_nursery -= 1
 
-    def should_pin(self, obj):
-        return True
-
     def shrink_array(self, obj, smallerlength):
         #
         # Only objects in the nursery can be "resized".  Resizing them
diff --git a/rpython/memory/gc/test/test_object_pinning.py b/rpython/memory/gc/test/test_object_pinning.py
--- a/rpython/memory/gc/test/test_object_pinning.py
+++ b/rpython/memory/gc/test/test_object_pinning.py
@@ -3,6 +3,8 @@
 from rpython.memory.gc.incminimark import IncrementalMiniMarkGC
 from test_direct import BaseDirectGCTest
 
+# YYY
+
 S = lltype.GcForwardReference()
 S.become(lltype.GcStruct('pinning_test_struct',
                          ('someInt', lltype.Signed),
@@ -172,6 +174,39 @@
         assert not self.gc.is_in_nursery(adr)
         assert self.gc.nursery_free == self.gc.nursery
         assert self.gc.nursery_top > self.gc.nursery
+    
+    # XXX test/define what happens if we try to pin an object that is too
+    # big for the nursery and will be raw-malloc'ed.
+
+    # XXX fill nursery with pinned objects -> + define behavior for such a
+    # case
+
+
+class TestIncminimarkFewPinnedObjects(BaseDirectGCTest):
+    from rpython.memory.gc.incminimark import IncrementalMiniMarkGC as GCClass
+
+    GC_PARAMS = {'max_number_of_pinned_objects': 5
+    }
+
+    def test_pinning_limit(self):
+        for instance_nr in xrange(self.GC_PARAMS['max_number_of_pinned_objects']):
+            ptr = self.malloc(S)
+            adr = llmemory.cast_ptr_to_adr(ptr)
+            ptr.someInt = 100 + instance_nr
+            self.stackroots.append(ptr)
+            self.gc.pin(adr)
+        #
+        # now we reached the maximum amount of pinned objects
+        ptr = self.malloc(S)
+        adr = llmemory.cast_ptr_to_adr(ptr)
+        self.stackroots.append(ptr)
+        assert not self.gc.pin(adr)
+
+class TestIncminimarkManyPinnedObjects(BaseDirectGCTest):
+    from rpython.memory.gc.incminimark import IncrementalMiniMarkGC as GCClass
+    
+    GC_PARAMS_PLENTY_PINNED_OBJECTS = {'max_number_of_pinned_objects': 50
+    }
 
     def get_max_nursery_objects(self, TYPE):
         typeid = self.get_type_id(TYPE)
@@ -181,18 +216,22 @@
 
     def test_full_pinned_nursery_pin_fail(self):
         object_mallocs = self.get_max_nursery_objects(S)
+        # just to be sure we do not run into the limit as we test not the limiter
+        # but rather the case of a nursery full with pinned objects.
+        assert object_mallocs < self.gc.max_number_of_pinned_objects
         for instance_nr in xrange(object_mallocs):
             ptr = self.malloc(S)
             adr = llmemory.cast_ptr_to_adr(ptr)
             ptr.someInt = 100 + instance_nr
             self.stackroots.append(ptr)
             self.gc.pin(adr)
+        #
         # nursery should be full now, at least no space for another `S`. Next malloc should fail.
         py.test.raises(Exception, self.malloc, S)
 
 
-    # XXX test/define what happens if we try to pin an object that is too
-    # big for the nursery and will be raw-malloc'ed.
+    # XXX check if we have to take chunk size of AddressStack in /rpython/memory/support.py into account.
+    # As far as gc-minimark-pinning tells us: yes (groggi)
 
-    # XXX fill nursery with pinned objects -> + define behavior for such a
-    # case
+
+


More information about the pypy-commit mailing list