Author: Stefan Beyer <[email protected]>
Branch: cpyext-gc-cycle
Changeset: r97320:adc05b1fd46b
Date: 2019-08-28 14:35 +0200
http://bitbucket.org/pypy/pypy/changeset/adc05b1fd46b/
Log: Adapted rrc gc to support incremental collections (still need to
reduce pauses)
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
@@ -2402,9 +2402,12 @@
self.visit_all_objects()
#
# If enabled, do a major collection step for rrc objects.
+ # TODO: move up before "if remaining >= estimate // 2" to
+ # improve pause times, issues:
+ # - (non-inc) mark expects all objects to be marked
+ # - both do not rescan nonstack-roots
if self.rrc_enabled:
- while not rrc_finished: # TODO: remove this line to do
incremental collection
- rrc_finished =
self.rrc_gc.major_collection_trace_step()
+ rrc_finished = self.rrc_gc.major_collection_trace_step()
else:
rrc_finished = True
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
@@ -12,9 +12,9 @@
self._debug_check_consistency(print_label="end-mark")
return True
- elif self.state == self.STATE_DEFAULT:
- # First, untrack all tuples with only non-gc rrc objects and
promote
- # all other tuples to the pyobj_list
+ if self.state == self.STATE_DEFAULT:
+ # First, untrack all tuples with only non-gc rrc objects and
+ # promote all other tuples to the pyobj_list
self._untrack_tuples()
merged_old_list = False
@@ -47,17 +47,25 @@
self.state = self.STATE_MARKING
return False
- elif self.state == self.STATE_MARKING:
+ if self.state == self.STATE_MARKING:
# mark all objects reachable from rawrefcounted roots
- self._mark_rawrefcount()
+ all_rrc_marked = self._mark_rawrefcount()
- self._debug_check_consistency(print_label="before-fin")
- self.state = self.STATE_GARBAGE_MARKING
+ if (all_rrc_marked and not self.gc.objects_to_trace.non_empty() and
+ not self.gc.more_objects_to_trace.non_empty()):
+ # all objects have been marked, dead objects will stay dead
+ self._debug_check_consistency(print_label="before-fin")
+ self.state = self.STATE_GARBAGE_MARKING
+
return False
- # now move all dead objs still in pyob_list to garbage
- # dead -> pyobj_old_list
- # live -> set cyclic refcount to > 0
+ # we are finished with marking, now finish things up
+ ll_assert(self.state == self.STATE_GARBAGE_MARKING, "invalid state")
+
+ # sync snapshot with pyob_list:
+ # * move all dead objs still in pyob_list to pyobj_old_list
+ # * for all other objects (in snapshot and new),
+ # set their cyclic refcount to > 0, to mark them as live
pygchdr = self.pyobj_list.c_gc_next
while pygchdr <> self.pyobj_list:
next_old = pygchdr.c_gc_next
@@ -75,13 +83,15 @@
pygchdr.c_gc_refs = 1 # new object, keep alive
pygchdr = next_old
- if self._find_garbage(False): # handle legacy finalizers
+ # handle legacy finalizers (assumption: not a lot of legacy finalizers,
+ # so no need to do it incrementally)
+ if self._find_garbage(False):
self._mark_garbage(False)
self._debug_check_consistency(print_label="end-legacy-fin")
self.state = self.STATE_DEFAULT
- # We are finished with marking, now finish things up
- found_finalizer = self._find_finalizer() # modern finalizers
+ # handle modern finalizers
+ found_finalizer = self._find_finalizer()
if found_finalizer:
self._gc_list_move(self.pyobj_old_list,
self.pyobj_isolate_list)
@@ -114,19 +124,22 @@
# as long as new objects with cyclic a refcount > 0 or alive border
# objects are found, increment the refcount of all referenced objects
# of those newly found objects
+ reached_limit = False
found_alive = True
+ simple_limit = 0
#
- while found_alive: # TODO: working set to improve performance?
+ while found_alive and not reached_limit: # TODO: working set to
improve performance?
found_alive = False
for i in range(0, self.total_objs):
obj = self.snapshot_objs[i]
found_alive |= self._mark_rawrefcount_obj(obj)
- #
- # now all rawrefcounted objects, which are alive, have a cyclic
- # refcount > 0 or are marked
+ simple_limit += 1
+ if simple_limit > 3:
+ reached_limit
+ return not reached_limit # are there any objects left?
def _mark_rawrefcount_obj(self, snapobj):
- if snapobj.status == 0:
+ if snapobj.status == 0: # already processed
return False
alive = snapobj.refcnt_external > 0
@@ -149,7 +162,7 @@
intobj = snapobj.pypy_link
obj = llmemory.cast_int_to_adr(intobj)
self.gc.objects_to_trace.append(obj)
- self.gc.visit_all_objects()
+ self.gc.visit_all_objects() # TODO: remove to improve pause
times
# mark as processed
snapobj.status = 0
return alive
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit