[pypy-commit] pypy default: Fix a complexity bug: if 'b' is a large bytearray,

arigo noreply at buildbot.pypy.org
Sat Jan 21 10:42:02 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r51561:a9118db9d0bc
Date: 2012-01-21 10:41 +0100
http://bitbucket.org/pypy/pypy/changeset/a9118db9d0bc/

Log:	Fix a complexity bug: if 'b' is a large bytearray,

	 b[small_slice] = small_string

	used to take a time proportional to how long the large bytearray is.

diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -624,8 +624,8 @@
 
     if step == 1:
         assert start >= 0
-        assert slicelength >= 0
-        del items[start:start+slicelength]
+        if slicelength > 0:
+            del items[start:start+slicelength]
     else:
         n = len(items)
         i = start
@@ -662,10 +662,11 @@
             while i >= lim:
                 items[i] = items[i-delta]
                 i -= 1
-        elif start >= 0:
+        elif delta == 0:
+            pass
+        else:
+            assert start >= 0   # start<0 is only possible with slicelength==0
             del items[start:start+delta]
-        else:
-            assert delta==0   # start<0 is only possible with slicelength==0
     elif len2 != slicelength:  # No resize for extended slices
         raise operationerrfmt(space.w_ValueError, "attempt to "
               "assign sequence of size %d to extended slice of size %d",
diff --git a/pypy/objspace/std/test/test_bytearrayobject.py b/pypy/objspace/std/test/test_bytearrayobject.py
--- a/pypy/objspace/std/test/test_bytearrayobject.py
+++ b/pypy/objspace/std/test/test_bytearrayobject.py
@@ -1,5 +1,9 @@
+from pypy import conftest
 
 class AppTestBytesArray:
+    def setup_class(cls):
+        cls.w_runappdirect = cls.space.wrap(conftest.option.runappdirect)
+
     def test_basics(self):
         b = bytearray()
         assert type(b) is bytearray
@@ -439,3 +443,15 @@
     def test_reduce(self):
         assert bytearray('caf\xe9').__reduce__() == (
             bytearray, (u'caf\xe9', 'latin-1'), None)
+
+    def test_setitem_slice_performance(self):
+        # because of a complexity bug, this used to take forever on a
+        # translated pypy.  On CPython2.6 -A, it takes around 8 seconds.
+        if self.runappdirect:
+            count = 16*1024*1024
+        else:
+            count = 1024
+        b = bytearray(count)
+        for i in range(count):
+            b[i:i+1] = 'y'
+        assert str(b) == 'y' * count


More information about the pypy-commit mailing list