[Python-checkins] cpython: Issue #25869: Optimized deepcopying ElementTree; it is now 20 times faster.

serhiy.storchaka python-checkins at python.org
Mon Dec 21 05:57:53 EST 2015


https://hg.python.org/cpython/rev/090c3e3a648d
changeset:   99656:090c3e3a648d
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Mon Dec 21 12:57:27 2015 +0200
summary:
  Issue #25869: Optimized deepcopying ElementTree; it is now 20 times faster.

files:
  Misc/NEWS              |   2 +
  Modules/_elementtree.c |  78 ++++++++++++++++++++---------
  2 files changed, 56 insertions(+), 24 deletions(-)


diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -115,6 +115,8 @@
 Library
 -------
 
+- Issue #25869: Optimized deepcopying ElementTree; it is now 20 times faster.
+
 - Issue #25873: Optimized iterating ElementTree.  Iterating elements
   Element.iter() is now 40% faster, iterating text Element.itertext()
   is now up to 2.5 times faster.
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -129,30 +129,6 @@
 /* helpers */
 
 LOCAL(PyObject*)
-deepcopy(PyObject* object, PyObject* memo)
-{
-    /* do a deep copy of the given object */
-    PyObject* args;
-    PyObject* result;
-    elementtreestate *st = ET_STATE_GLOBAL;
-
-    if (!st->deepcopy_obj) {
-        PyErr_SetString(
-            PyExc_RuntimeError,
-            "deepcopy helper not found"
-            );
-        return NULL;
-    }
-
-    args = PyTuple_Pack(2, object, memo);
-    if (!args)
-        return NULL;
-    result = PyObject_CallObject(st->deepcopy_obj, args);
-    Py_DECREF(args);
-    return result;
-}
-
-LOCAL(PyObject*)
 list_join(PyObject* list)
 {
     /* join list elements (destroying the list in the process) */
@@ -748,6 +724,9 @@
     return (PyObject*) element;
 }
 
+/* Helper for a deep copy. */
+LOCAL(PyObject *) deepcopy(PyObject *, PyObject *);
+
 /*[clinic input]
 _elementtree.Element.__deepcopy__
 
@@ -838,6 +817,57 @@
     return NULL;
 }
 
+LOCAL(PyObject *)
+deepcopy(PyObject *object, PyObject *memo)
+{
+    /* do a deep copy of the given object */
+    PyObject *args;
+    PyObject *result;
+    elementtreestate *st;
+
+    /* Fast paths */
+    if (object == Py_None || PyUnicode_CheckExact(object)) {
+        Py_INCREF(object);
+        return object;
+    }
+
+    if (Py_REFCNT(object) == 1) {
+        if (PyDict_CheckExact(object)) {
+            PyObject *key, *value;
+            Py_ssize_t pos = 0;
+            int simple = 1;
+            while (PyDict_Next(object, &pos, &key, &value)) {
+                if (!PyUnicode_CheckExact(key) || !PyUnicode_CheckExact(value)) {
+                    simple = 0;
+                    break;
+                }
+            }
+            if (simple)
+                return PyDict_Copy(object);
+            /* Fall through to general case */
+        }
+        else if (Element_CheckExact(object)) {
+            return _elementtree_Element___deepcopy__((ElementObject *)object, memo);
+        }
+    }
+
+    /* General case */
+    st = ET_STATE_GLOBAL;
+    if (!st->deepcopy_obj) {
+        PyErr_SetString(PyExc_RuntimeError,
+                        "deepcopy helper not found");
+        return NULL;
+    }
+
+    args = PyTuple_Pack(2, object, memo);
+    if (!args)
+        return NULL;
+    result = PyObject_CallObject(st->deepcopy_obj, args);
+    Py_DECREF(args);
+    return result;
+}
+
+
 /*[clinic input]
 _elementtree.Element.__sizeof__ -> Py_ssize_t
 

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


More information about the Python-checkins mailing list