[pypy-commit] pypy default: Tweak: 16% speed increase of PyPy annotation, by avoiding the
arigo
pypy.commits at gmail.com
Sun Nov 19 18:33:13 EST 2017
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r93086:60c4fa1b0539
Date: 2017-11-20 00:32 +0100
http://bitbucket.org/pypy/pypy/changeset/60c4fa1b0539/
Log: Tweak: 16% speed increase of PyPy annotation, by avoiding the
situation where a block is rescheduled many many times before it is
finally resolved (e.g. because resolving it requires (re)flowing
through a very long chain of blocks).
diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py
--- a/rpython/annotator/annrpython.py
+++ b/rpython/annotator/annrpython.py
@@ -33,7 +33,7 @@
translator = TranslationContext()
translator.annotator = self
self.translator = translator
- self.pendingblocks = {} # map {block: graph-containing-it}
+ self.genpendingblocks=[{}] # [{block: graph-containing-it}] * generation
self.annotated = {} # set of blocks already seen
self.added_blocks = None # see processblock() below
self.links_followed = {} # set of links that have ever been followed
@@ -57,7 +57,7 @@
self.errors = []
def __getstate__(self):
- attrs = """translator pendingblocks annotated links_followed
+ attrs = """translator genpendingblocks annotated links_followed
notify bookkeeper frozen policy added_blocks""".split()
ret = self.__dict__.copy()
for key, value in ret.items():
@@ -188,18 +188,39 @@
else:
self.mergeinputargs(graph, block, cells)
if not self.annotated[block]:
- self.pendingblocks[block] = graph
+ self.schedulependingblock(graph, block)
+
+ def schedulependingblock(self, graph, block):
+ # 'self.genpendingblocks' is a list of dictionaries which is
+ # logically equivalent to just one dictionary. But we keep a
+ # 'generation' number on each block (=key), and whenever we
+ # process a block, we increase its generation number. The
+ # block is added to the 'genpendingblocks' indexed by its
+ # generation number. See complete_pending_blocks() below.
+ generation = getattr(block, 'generation', 0)
+ self.genpendingblocks[generation][block] = graph
def complete_pending_blocks(self):
- while self.pendingblocks:
- # Grab all blocks from 'self.pendingblocks' in a list, and
- # walk that list. This prevents a situation where the same
- # block is added over and over again to 'self.pendingblocks'
- # and the code here would pop that same block from the dict
- # over and over again, without ever looking at other blocks.
- all_blocks = self.pendingblocks.keys()
- for block in all_blocks:
- graph = self.pendingblocks.pop(block)
+ while True:
+ # Find the first of the dictionaries in 'self.genpendingblocks'
+ # which is not empty
+ gen = 0
+ for pendingblocks in self.genpendingblocks:
+ if pendingblocks:
+ break
+ gen += 1
+ else:
+ return # all empty => done
+
+ gen += 1 # next generation number
+ if len(self.genpendingblocks) == gen:
+ self.genpendingblocks.append({})
+
+ # Process all blocks at this level
+ # (if any gets re-inserted, it will be into the next level)
+ while pendingblocks:
+ block, graph = pendingblocks.popitem()
+ block.generation = gen
self.processblock(graph, block)
def complete(self):
@@ -207,7 +228,7 @@
while True:
self.complete_pending_blocks()
self.policy.no_more_blocks_to_annotate(self)
- if not self.pendingblocks:
+ if not any(self.genpendingblocks):
break # finished
# make sure that the return variables of all graphs is annotated
if self.added_blocks is not None:
@@ -393,7 +414,7 @@
def reflowpendingblock(self, graph, block):
assert not self.frozen
assert graph not in self.fixed_graphs
- self.pendingblocks[block] = graph
+ self.schedulependingblock(graph, block)
assert block in self.annotated
self.annotated[block] = False # must re-flow
self.blocked_blocks[block] = (graph, None)
diff --git a/rpython/flowspace/model.py b/rpython/flowspace/model.py
--- a/rpython/flowspace/model.py
+++ b/rpython/flowspace/model.py
@@ -170,7 +170,7 @@
class Block(object):
__slots__ = """inputargs operations exitswitch
- exits blockcolor""".split()
+ exits blockcolor generation""".split()
def __init__(self, inputargs):
self.inputargs = list(inputargs) # mixed list of variable/const XXX
More information about the pypy-commit
mailing list