[pypy-commit] pypy cpyext-gc-cycle: Implemented incremental limit for non-rrc objects during rrc marking

stevie_92 pypy.commits at gmail.com
Thu Nov 21 10:33:01 EST 2019


Author: Stefan Beyer <home at sbeyer.at>
Branch: cpyext-gc-cycle
Changeset: r98130:6a71ef8d2b2c
Date: 2019-11-21 15:50 +0100
http://bitbucket.org/pypy/pypy/changeset/6a71ef8d2b2c/

Log:	Implemented incremental limit for non-rrc objects during rrc marking
	Added flag to enable/disable tuple untracking for debugging

diff --git a/rpython/memory/gc/rrc/base.py b/rpython/memory/gc/rrc/base.py
--- a/rpython/memory/gc/rrc/base.py
+++ b/rpython/memory/gc/rrc/base.py
@@ -84,6 +84,8 @@
     RAWREFCOUNT_REFS_UNTRACKED = -2 << RAWREFCOUNT_REFS_SHIFT
     RAWREFCOUNT_REFS_REACHABLE = -3 << RAWREFCOUNT_REFS_SHIFT
 
+    UNTRACK_TUPLES_DEFAULT = True
+
     def _pyobj(self, pyobjaddr):
         return llmemory.cast_adr_to_ptr(pyobjaddr, self.PYOBJ_HDR_PTR)
     def _pygchdr(self, pygchdraddr):
@@ -124,6 +126,13 @@
         self.state = self.STATE_DEFAULT
         self.marking_state = 0
         inc_limit = env.read_uint_from_env('PYPY_RRC_GC_INCREMENT_STEP')
+        untrack = env.read_uint_from_env('PYPY_RRC_GC_UNTRACK_TUPLES')
+        if untrack == 1:
+            self.untrack_tuples = True
+        elif untrack == 2:
+            self.untrack_tuples = False
+        else:
+            self.untrack_tuples = self.UNTRACK_TUPLES_DEFAULT
         if inc_limit > 0:
             self.inc_limit = inc_limit
         else:
@@ -469,17 +478,20 @@
             self._free(pyobject, True)
 
     def _untrack_tuples(self):
-        gchdr = self.tuple_list.c_gc_next
-        while gchdr <> self.tuple_list:
-            gchdr_next = gchdr.c_gc_next
-            pyobj = self.gc_as_pyobj(gchdr)
-            result = self.tuple_maybe_untrack(pyobj)
-            if result == 1: # contains gc objects -> promote to pyobj list
-                next = gchdr.c_gc_next
-                next.c_gc_prev = gchdr.c_gc_prev
-                gchdr.c_gc_prev.c_gc_next = next
-                self._gc_list_add(self.pyobj_list, gchdr)
-            gchdr = gchdr_next
+        if self.untrack_tuples:
+            self._debug_check_consistency(print_label="before-untrack")
+            gchdr = self.tuple_list.c_gc_next
+            while gchdr <> self.tuple_list:
+                gchdr_next = gchdr.c_gc_next
+                pyobj = self.gc_as_pyobj(gchdr)
+                result = self.tuple_maybe_untrack(pyobj)
+                if result == 1: # contains gc objects -> promote to pyobj list
+                    next = gchdr.c_gc_next
+                    next.c_gc_prev = gchdr.c_gc_prev
+                    gchdr.c_gc_prev.c_gc_next = next
+                    self._gc_list_add(self.pyobj_list, gchdr)
+                gchdr = gchdr_next
+            self._debug_check_consistency(print_label="after-untrack")
 
     def _find_garbage(self, use_dict):
         found_garbage = False
diff --git a/rpython/memory/gc/rrc/incmark.py b/rpython/memory/gc/rrc/incmark.py
--- a/rpython/memory/gc/rrc/incmark.py
+++ b/rpython/memory/gc/rrc/incmark.py
@@ -2,6 +2,7 @@
 from rpython.rtyper.lltypesystem import rffi
 from rpython.memory.gc.rrc.base import RawRefCountBaseGC
 from rpython.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
+from rpython.rlib.rarithmetic import intmask
 import time
 
 class RawRefCountIncMarkGC(RawRefCountBaseGC):
@@ -367,9 +368,22 @@
                 snapobj.refcnt += 1
                 self._mark_rawrefcount_obj(snapobj)
                 simple_limit += 1
-                if simple_limit > self.inc_limit: # TODO: add test
+                if simple_limit > intmask(self.inc_limit): # TODO: add test
                     reached_limit = True
-            self.gc.visit_all_objects()  # TODO: implement sane limit
+
+            if not reached_limit:
+                # "split" the limit between rrc and non-rrc
+                # if 25% of rrc limit have been used, now use max 75% or non-rrc limit
+                if simple_limit > 0:
+                    estimate = intmask(self.gc.gc_increment_step) * intmask(self.inc_limit) / simple_limit
+                else:
+                    estimate = intmask(self.gc.gc_increment_step)
+                remaining = self.gc.visit_all_objects_step(estimate)
+                if remaining == 0:
+                    reached_limit = True
+                else:
+                    # if 25% of the non-rrc limit have been used, add 25% of the rrc limit to the counter
+                    simple_limit += intmask(self.inc_limit) * remaining / estimate
             first = False
         return not reached_limit # are there any objects left?
 
diff --git a/rpython/memory/gc/rrc/simple.py b/rpython/memory/gc/rrc/simple.py
--- a/rpython/memory/gc/rrc/simple.py
+++ b/rpython/memory/gc/rrc/simple.py
@@ -2,6 +2,12 @@
 
 class RawRefCountSimpleGC(RawRefCountBaseGC):
 
+    UNTRACK_TUPLES_DEFAULT = False
+
     def major_collection_trace_step(self):
+        self._untrack_tuples()
         self.p_list_old.foreach(self._major_trace, (False, False))
-        return True
\ No newline at end of file
+        return True
+
+    def visit_pyobj(self, gcobj):
+        pass
\ No newline at end of file


More information about the pypy-commit mailing list