]> granicus.if.org Git - python/commitdiff
SF bug #1085744: Performance issues with PySequence_Tuple()
authorRaymond Hettinger <python@rcn.com>
Thu, 16 Dec 2004 10:38:38 +0000 (10:38 +0000)
committerRaymond Hettinger <python@rcn.com>
Thu, 16 Dec 2004 10:38:38 +0000 (10:38 +0000)
* Added missing error checks.
* Fixed O(n**2) growth pattern.  Modeled after lists to achieve linear
  amortized resizing.  Improves construction of "tuple(it)" when "it" is
  large and does not have a __len__ method.  Other cases are unaffected.

Objects/abstract.c

index 377f359300d3e719a2f95d0032d935326b22e3b6..b98100155e4165b5161b253c0372bff0a92b9c30 100644 (file)
@@ -1427,10 +1427,20 @@ PySequence_Tuple(PyObject *v)
                        break;
                }
                if (j >= n) {
-                       if (n < 500)
-                               n += 10;
-                       else
-                               n += 100;
+                       int oldn = n;
+                       /* The over-allocation strategy can grow a bit faster
+                          than for lists because unlike lists the 
+                          over-allocation isn't permanent -- we reclaim
+                          the excess before the end of this routine.
+                          So, grow by ten and then add 25%.
+                       */
+                       n += 10;
+                       n += n >> 2;
+                       if (n < oldn) {
+                               /* Check for overflow */
+                               PyErr_NoMemory();
+                               goto Fail; 
+                       }
                        if (_PyTuple_Resize(&result, n) != 0) {
                                Py_DECREF(item);
                                goto Fail;