Author: Armin Rigo <ar...@tunes.org> Branch: counter-decay Changeset: r50746:5f38cbc2c7f7 Date: 2011-12-20 09:30 +0100 http://bitbucket.org/pypy/pypy/changeset/5f38cbc2c7f7/
Log: Simplify and "stand-alone-ize" the clean-up of old jitcells from the jitcell dict. diff --git a/pypy/jit/metainterp/test/test_warmstate.py b/pypy/jit/metainterp/test/test_warmstate.py --- a/pypy/jit/metainterp/test/test_warmstate.py +++ b/pypy/jit/metainterp/test/test_warmstate.py @@ -277,65 +277,50 @@ assert res is True def test_cleanup_jitcell_dict(): - from pypy.jit.metainterp.memmgr import MemoryManager - class FakeWarmRunnerDesc: - memory_manager = MemoryManager() - class cpu: - pass class FakeJitDriverSD: _green_args_spec = [lltype.Signed] # # Test creating tons of jitcells that remain at 0 - warmstate = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) + warmstate = WarmEnterState(None, FakeJitDriverSD()) get_jitcell = warmstate._make_jitcell_getter_default() cell1 = get_jitcell(True, -1) assert len(warmstate._jitcell_dict) == 1 - assert FakeWarmRunnerDesc.memory_manager.current_generation == 1 # for i in range(1, 20005): get_jitcell(True, i) # should trigger a clean-up at 20001 assert len(warmstate._jitcell_dict) == (i % 20000) + 1 - assert FakeWarmRunnerDesc.memory_manager.current_generation == 2 # # Same test, with one jitcell that has a counter of BASE instead of 0 - warmstate = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) - warmstate.set_param_decay_halflife(2) - warmstate.set_param_threshold(5) - warmstate.set_param_function_threshold(0) + warmstate = WarmEnterState(None, FakeJitDriverSD()) get_jitcell = warmstate._make_jitcell_getter_default() cell2 = get_jitcell(True, -2) - cell2.counter = BASE = warmstate.increment_threshold * 3 + cell2.counter = BASE = warmstate.THRESHOLD_LIMIT // 2 # 50% # for i in range(0, 20005): get_jitcell(True, i) assert len(warmstate._jitcell_dict) == (i % 19999) + 2 # assert cell2 in warmstate._jitcell_dict.values() - assert cell2.counter == int(BASE * math.sqrt(0.5)) # decayed once - assert FakeWarmRunnerDesc.memory_manager.current_generation == 3 + assert cell2.counter == int(BASE * 0.92) # decayed once # - # Same test, with jitcells that are compiled and free by the memmgr - warmstate = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) + # Same test, with jitcells that are compiled and freed by the memmgr + warmstate = WarmEnterState(None, FakeJitDriverSD()) get_jitcell = warmstate._make_jitcell_getter_default() get_jitcell(True, -1) - assert FakeWarmRunnerDesc.memory_manager.current_generation == 3 # for i in range(1, 20005): cell = get_jitcell(True, i) cell.counter = -1 cell.wref_procedure_token = None # or a dead weakref, equivalently assert len(warmstate._jitcell_dict) == (i % 20000) + 1 - assert FakeWarmRunnerDesc.memory_manager.current_generation == 4 # # Same test, with counter == -2 (rare case, kept alive) - warmstate = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD()) + warmstate = WarmEnterState(None, FakeJitDriverSD()) get_jitcell = warmstate._make_jitcell_getter_default() cell = get_jitcell(True, -1) cell.counter = -2 - assert FakeWarmRunnerDesc.memory_manager.current_generation == 4 # for i in range(1, 20005): cell = get_jitcell(True, i) cell.counter = -2 assert len(warmstate._jitcell_dict) == i + 1 - assert FakeWarmRunnerDesc.memory_manager.current_generation == 5 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 @@ -446,44 +446,32 @@ except AttributeError: pass # - memmgr = self.warmrunnerdesc and self.warmrunnerdesc.memory_manager - if memmgr: - def _cleanup_dict(): - minimum = sys.maxint - if self.increment_threshold > 0: - minimum = min(minimum, self.increment_threshold) - if self.increment_function_threshold > 0: - minimum = min(minimum, 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) - elif (cell.counter == -1 - and cell.get_procedure_token() is None): + def _cleanup_dict(): + minimum = self.THRESHOLD_LIMIT // 20 # minimum 5% + killme = [] + for key, cell in jitcell_dict.iteritems(): + if cell.counter >= 0: + cell.counter = int(cell.counter * 0.92) + 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 - self._jitcell_dict = jitcell_dict # for tests - memmgr.record_jitcell_dict(_cleanup_dict) - else: - def _maybe_cleanup_dict(): - pass + elif (cell.counter == -1 + and cell.get_procedure_token() is None): + killme.append(key) + for key in killme: + del jitcell_dict[key] + # + def _maybe_cleanup_dict(): + # Once in a while, rarely, when too many entries have + # been put in the jitdict_dict, we do a cleanup phase: + # we decay all counters and kill entries with a too + # low counter. + self._trigger_automatic_cleanup += 1 + if self._trigger_automatic_cleanup > 20000: + self._trigger_automatic_cleanup = 0 + _cleanup_dict() + # + self._trigger_automatic_cleanup = 0 + self._jitcell_dict = jitcell_dict # for tests # def get_jitcell(build, *greenargs): try: @@ -503,7 +491,7 @@ 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() + # note that there is no equivalent of _maybe_cleanup_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. _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit