Author: Armin Rigo <[email protected]>
Branch:
Changeset: r91568:6cbfa075de61
Date: 2017-06-07 18:47 +0200
http://bitbucket.org/pypy/pypy/changeset/6cbfa075de61/
Log: Don't preallocate RPython lists if we only know an upper bound on
the final size. See comments.
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -410,6 +410,7 @@
self.listdef.resize()
self.listdef.listitem.hint_maxlength = True
elif 'fence' in hints:
+ self.listdef.resize()
self = self.listdef.offspring(getbookkeeper())
return self
diff --git a/rpython/translator/simplify.py b/rpython/translator/simplify.py
--- a/rpython/translator/simplify.py
+++ b/rpython/translator/simplify.py
@@ -1005,6 +1005,16 @@
# - add a hint(vlist, iterable, {'maxlength'}) in the iterblock,
# where we can compute the known maximum length
+ # - new in June 2017: we do that only if 'exactlength' is True.
+ # found some real use cases where the over-allocation scheme
+ # was over-allocating far too much: the loop would only append
+ # an item to the list after 'if some rare condition:'. By
+ # dropping this hint, we disable preallocation and cause the
+ # append() to be done by checking the size, but still, after
+ # the loop, we will turn the list into a fixed-size one.
+ # ('maxlength_inexact' is never processed elsewhere; the hint
+ # is still needed to prevent this function from being entered
+ # in an infinite loop)
link = iterblock.exits[0]
vlist = self.contains_vlist(link.args)
assert vlist
@@ -1014,7 +1024,8 @@
break
else:
raise AssertionError("lost 'iter' operation")
- chint = Constant({'maxlength': True})
+ chint = Constant({'maxlength' if exactlength else 'maxlength_inexact':
+ True})
hint = op.hint(vlist, hlop.args[0], chint)
iterblock.operations.append(hint)
link.args = list(link.args)
diff --git a/rpython/translator/test/test_simplify.py
b/rpython/translator/test/test_simplify.py
--- a/rpython/translator/test/test_simplify.py
+++ b/rpython/translator/test/test_simplify.py
@@ -336,11 +336,14 @@
interp = LLInterpreter(t.rtyper)
return interp, graph
- def no_resize(self, graph):
+ def no_resize(self, graph, expect_resize=0):
+ found_resize = 0
for block in graph.iterblocks():
for op in block.operations:
if op.opname == 'direct_call':
- assert 'list_resize' not in repr(op.args[0])
+ if 'list_resize' in repr(op.args[0]):
+ found_resize += 1
+ assert found_resize == expect_resize
def test_simple(self):
def main(n):
@@ -367,7 +370,8 @@
interp, graph = self.specialize(main, [int])
res = interp.eval_graph(graph, [10])
assert res == 5
- self.no_resize(graph)
+ self.no_resize(graph, expect_resize=1)
+ # the non-exactness disables preallocating now, for sanity
def test_mutated_after_listcomp(self):
def main(n):
@@ -379,6 +383,7 @@
assert res == 5 * 17
res = interp.eval_graph(graph, [5])
assert res == -42
+ self.no_resize(graph, expect_resize=1) # after the loop
def test_two_loops(self):
def main(n, m):
@@ -397,6 +402,7 @@
interp, graph = self.specialize(main, [int, int])
res = interp.eval_graph(graph, [8, 3])
assert res == 28 - 3
+ self.no_resize(graph)
def test_dict(self):
def main(n, m):
@@ -408,6 +414,7 @@
assert res == 2 + 8 * 17 + 5 * 17
res = interp.eval_graph(graph, [4, 4])
assert res == 1 + 4 * 17 + 4 * 17
+ self.no_resize(graph)
def test_list_iterator(self):
@@ -452,3 +459,4 @@
interp, graph = self.specialize(main, [int])
res = interp.eval_graph(graph, [10])
assert res == 5 * 17
+ self.no_resize(graph)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit