Author: Armin Rigo <ar...@tunes.org>
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
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to