[pypy-commit] pypy counter-decay: Fix yet another obscure case in which we can end up with an apparent

arigo noreply at buildbot.pypy.org
Thu Dec 15 11:04:36 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: counter-decay
Changeset: r50541:ba32c0042356
Date: 2011-12-15 01:43 +0100
http://bitbucket.org/pypy/pypy/changeset/ba32c0042356/

Log:	Fix yet another obscure case in which we can end up with an apparent
	leak.

diff --git a/pypy/jit/metainterp/memmgr.py b/pypy/jit/metainterp/memmgr.py
--- a/pypy/jit/metainterp/memmgr.py
+++ b/pypy/jit/metainterp/memmgr.py
@@ -50,9 +50,9 @@
             self.check_frequency = check_frequency
             self.next_check = self.current_generation + 1
 
-    def next_generation(self):
+    def next_generation(self, do_cleanups_now=True):
         self.current_generation += 1
-        if self.current_generation == self.next_check:
+        if do_cleanups_now and self.current_generation >= self.next_check:
             self._kill_old_loops_now()
             self._cleanup_jitcell_dicts()
             self.next_check = self.current_generation + self.check_frequency
@@ -89,7 +89,7 @@
         To use only as an approximation for decaying counters."""
         return r_uint(self.current_generation)
 
-    def record_jitcell_dict(self, warmstate, jitcell_dict):
+    def record_jitcell_dict(self, callback):
         """NOT_RPYTHON.  The given jitcell_dict is a dict that needs
         occasional clean-ups of old cells.  A cell is old if it never
         reached the threshold, and its counter decayed to a tiny value."""
@@ -97,17 +97,7 @@
         # so we have to make a different function for each one.  These
         # functions are chained to each other: each calls the previous one.
         def cleanup_dict():
-            minimum = min(warmstate.increment_threshold,
-                          warmstate.increment_function_threshold)
-            current = self.get_current_generation_uint()
-            killme = []
-            for key, cell in jitcell_dict.iteritems():
-                if cell.counter >= 0:
-                    cell.adjust_counter(current, warmstate.log_decay_factor)
-                    if cell.counter < minimum:
-                        killme.append(key)
-            for key in killme:
-                del jitcell_dict[key]
+            callback()
             cleanup_previous()
         #
         cleanup_previous = self._cleanup_jitcell_dicts
diff --git a/pypy/jit/metainterp/warmstate.py b/pypy/jit/metainterp/warmstate.py
--- a/pypy/jit/metainterp/warmstate.py
+++ b/pypy/jit/metainterp/warmstate.py
@@ -490,9 +490,38 @@
             self.warmrunnerdesc.stats.jitcell_dicts.append(jitcell_dict)
         except AttributeError:
             pass
-        memmgr = self.warmrunnerdesc.memory_manager
+        #
+        memmgr = self.warmrunnerdesc and self.warmrunnerdesc.memory_manager
         if memmgr:
-            memmgr.record_jitcell_dict(self, jitcell_dict)
+            def _cleanup_dict():
+                minimum = min(self.increment_threshold,
+                              self.increment_function_threshold)
+                currentgen = memmgr.get_current_generation_uint()
+                killme = []
+                for key, cell in jitcell_dict.iteritems():
+                    if cell.counter >= 0:
+                        cell.adjust_counter(currentgen, self.log_decay_factor)
+                        if cell.counter < minimum:
+                            killme.append(key)
+                for key in killme:
+                    del jitcell_dict[key]
+            #
+            def _maybe_cleanup_dict():
+                # If no tracing goes on at all because the jitcells are
+                # each time for new greenargs, the dictionary grows forever.
+                # So every one in a (rare) while, we decide to force an
+                # artificial next_generation() and _cleanup_dict().
+                self._trigger_automatic_cleanup += 1
+                if self._trigger_automatic_cleanup > 20000:
+                    self._trigger_automatic_cleanup = 0
+                    memmgr.next_generation(do_cleanups_now=False)
+                    _cleanup_dict()
+            #
+            self._trigger_automatic_cleanup = 0
+            memmgr.record_jitcell_dict(_cleanup_dict)
+        else:
+            def _maybe_cleanup_dict():
+                pass
         #
         def get_jitcell(build, *greenargs):
             try:
@@ -500,6 +529,7 @@
             except KeyError:
                 if not build:
                     return None
+                _maybe_cleanup_dict()
                 cell = self._new_jitcell()
                 jitcell_dict[greenargs] = cell
             return cell


More information about the pypy-commit mailing list