[pypy-commit] pypy counter-decay: Not tested: clean up the jitcell_dicts that are used internally. This

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


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

Log:	Not tested: clean up the jitcell_dicts that are used internally.
	This is probably important to ensure that a long-running process
	cannot "leak" arbitrary amounts of memory due to having more and
	more JitCells stored in these big dicts.

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
@@ -38,6 +38,7 @@
         self.current_generation = r_int64(1)
         self.next_check = r_int64(-1)
         self.alive_loops = {}
+        self._cleanup_jitcell_dicts = lambda: None
 
     def set_max_age(self, max_age, check_frequency=0):
         if max_age <= 0:
@@ -53,6 +54,7 @@
         self.current_generation += 1
         if self.current_generation == self.next_check:
             self._kill_old_loops_now()
+            self._cleanup_jitcell_dicts()
             self.next_check = self.current_generation + self.check_frequency
 
     def keep_loop_alive(self, looptoken):
@@ -86,3 +88,27 @@
         """Return the current generation, possibly truncated to a uint.
         To use only as an approximation for decaying counters."""
         return r_uint(self.current_generation)
+
+    def record_jitcell_dict(self, warmstate, jitcell_dict):
+        """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."""
+        # note that the various jitcell_dicts have different RPython types,
+        # 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]
+            cleanup_previous()
+        #
+        cleanup_previous = self._cleanup_jitcell_dicts
+        self._cleanup_jitcell_dicts = cleanup_dict
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
@@ -190,7 +190,6 @@
 
 class WarmEnterState(object):
     THRESHOLD_LIMIT = sys.maxint // 2
-    default_jitcell_dict = None
 
     def __init__(self, warmrunnerdesc, jitdriver_sd):
         "NOT_RPYTHON"
@@ -491,6 +490,9 @@
             self.warmrunnerdesc.stats.jitcell_dicts.append(jitcell_dict)
         except AttributeError:
             pass
+        memmgr = self.warmrunnerdesc.memory_manager
+        if memmgr:
+            memmgr.record_jitcell_dict(self, jitcell_dict)
         #
         def get_jitcell(build, *greenargs):
             try:
@@ -509,6 +511,10 @@
         get_jitcell_at_ptr = self.jitdriver_sd._get_jitcell_at_ptr
         set_jitcell_at_ptr = self.jitdriver_sd._set_jitcell_at_ptr
         lltohlhack = {}
+        # note that there is no equivalent of record_jitcell_dict()
+        # in the case of custom getters.  We assume that the interpreter
+        # stores the JitCells on some objects that can go away by GC,
+        # like the PyCode objects in PyPy.
         #
         def get_jitcell(build, *greenargs):
             fn = support.maybe_on_top_of_llinterp(rtyper, get_jitcell_at_ptr)


More information about the pypy-commit mailing list