[Python-checkins] cpython: Add a fast path (no iterator creation) for a common case for repeating deques

raymond.hettinger python-checkins at python.org
Sat Sep 19 18:05:49 CEST 2015


https://hg.python.org/cpython/rev/4c99c6eab05f
changeset:   98072:4c99c6eab05f
user:        Raymond Hettinger <python at rcn.com>
date:        Sat Sep 19 09:05:42 2015 -0700
summary:
  Add a fast path (no iterator creation) for a common case for repeating deques of size 1

files:
  Lib/test/test_deque.py       |   9 +++++++++
  Modules/_collectionsmodule.c |  15 +++++++++++----
  2 files changed, 20 insertions(+), 4 deletions(-)


diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py
--- a/Lib/test/test_deque.py
+++ b/Lib/test/test_deque.py
@@ -654,6 +654,15 @@
         self.assertNotEqual(id(d), id(e))
         self.assertEqual(list(d), list(e))
 
+        for i in range(5):
+            for maxlen in range(-1, 6):
+                s = [random.random() for j in range(i)]
+                d = deque(s) if maxlen == -1 else deque(s, maxlen)
+                e = d.copy()
+                self.assertEqual(d, e)
+                self.assertEqual(d.maxlen, e.maxlen)
+                self.assertTrue(all(x is y for x, y in zip(d, e)))
+
     def test_copy_method(self):
         mut = [10]
         d = deque([mut])
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -1211,6 +1211,7 @@
 static PyObject *
 deque_copy(PyObject *deque)
 {
+    dequeobject *old_deque = (dequeobject *)deque;
     if (Py_TYPE(deque) == &deque_type) {
         dequeobject *new_deque;
         PyObject *rv;
@@ -1218,8 +1219,14 @@
         new_deque = (dequeobject *)deque_new(&deque_type, (PyObject *)NULL, (PyObject *)NULL);
         if (new_deque == NULL)
             return NULL;
-        new_deque->maxlen = ((dequeobject *)deque)->maxlen;
-        rv = deque_extend(new_deque, deque);
+        new_deque->maxlen = old_deque->maxlen;
+        /* Fast path for the deque_repeat() common case where len(deque) == 1 */
+        if (Py_SIZE(deque) == 1 && new_deque->maxlen != 0) {
+            PyObject *item = old_deque->leftblock->data[old_deque->leftindex];
+            rv = deque_append(new_deque, item);
+        } else {
+            rv = deque_extend(new_deque, deque);
+        }
         if (rv != NULL) {
             Py_DECREF(rv);
             return (PyObject *)new_deque;
@@ -1227,11 +1234,11 @@
         Py_DECREF(new_deque);
         return NULL;
     }
-    if (((dequeobject *)deque)->maxlen == -1)
+    if (old_deque->maxlen == -1)
         return PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "O", deque, NULL);
     else
         return PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "Oi",
-            deque, ((dequeobject *)deque)->maxlen, NULL);
+            deque, old_deque->maxlen, NULL);
 }
 
 PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque.");

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list