Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 060ed71

Browse files
Issue #25869: Optimized deepcopying ElementTree; it is now 20 times faster.
1 parent 22adf2a commit 060ed71

2 files changed

Lines changed: 56 additions & 24 deletions

File tree

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ Core and Builtins
115115
Library
116116
-------
117117

118+
- Issue #25869: Optimized deepcopying ElementTree; it is now 20 times faster.
119+
118120
- Issue #25873: Optimized iterating ElementTree. Iterating elements
119121
Element.iter() is now 40% faster, iterating text Element.itertext()
120122
is now up to 2.5 times faster.

Modules/_elementtree.c

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -128,30 +128,6 @@ elementtree_free(void *m)
128128

129129
/* helpers */
130130

131-
LOCAL(PyObject*)
132-
deepcopy(PyObject* object, PyObject* memo)
133-
{
134-
/* do a deep copy of the given object */
135-
PyObject* args;
136-
PyObject* result;
137-
elementtreestate *st = ET_STATE_GLOBAL;
138-
139-
if (!st->deepcopy_obj) {
140-
PyErr_SetString(
141-
PyExc_RuntimeError,
142-
"deepcopy helper not found"
143-
);
144-
return NULL;
145-
}
146-
147-
args = PyTuple_Pack(2, object, memo);
148-
if (!args)
149-
return NULL;
150-
result = PyObject_CallObject(st->deepcopy_obj, args);
151-
Py_DECREF(args);
152-
return result;
153-
}
154-
155131
LOCAL(PyObject*)
156132
list_join(PyObject* list)
157133
{
@@ -748,6 +724,9 @@ _elementtree_Element___copy___impl(ElementObject *self)
748724
return (PyObject*) element;
749725
}
750726

727+
/* Helper for a deep copy. */
728+
LOCAL(PyObject *) deepcopy(PyObject *, PyObject *);
729+
751730
/*[clinic input]
752731
_elementtree.Element.__deepcopy__
753732
@@ -838,6 +817,57 @@ _elementtree_Element___deepcopy__(ElementObject *self, PyObject *memo)
838817
return NULL;
839818
}
840819

820+
LOCAL(PyObject *)
821+
deepcopy(PyObject *object, PyObject *memo)
822+
{
823+
/* do a deep copy of the given object */
824+
PyObject *args;
825+
PyObject *result;
826+
elementtreestate *st;
827+
828+
/* Fast paths */
829+
if (object == Py_None || PyUnicode_CheckExact(object)) {
830+
Py_INCREF(object);
831+
return object;
832+
}
833+
834+
if (Py_REFCNT(object) == 1) {
835+
if (PyDict_CheckExact(object)) {
836+
PyObject *key, *value;
837+
Py_ssize_t pos = 0;
838+
int simple = 1;
839+
while (PyDict_Next(object, &pos, &key, &value)) {
840+
if (!PyUnicode_CheckExact(key) || !PyUnicode_CheckExact(value)) {
841+
simple = 0;
842+
break;
843+
}
844+
}
845+
if (simple)
846+
return PyDict_Copy(object);
847+
/* Fall through to general case */
848+
}
849+
else if (Element_CheckExact(object)) {
850+
return _elementtree_Element___deepcopy__((ElementObject *)object, memo);
851+
}
852+
}
853+
854+
/* General case */
855+
st = ET_STATE_GLOBAL;
856+
if (!st->deepcopy_obj) {
857+
PyErr_SetString(PyExc_RuntimeError,
858+
"deepcopy helper not found");
859+
return NULL;
860+
}
861+
862+
args = PyTuple_Pack(2, object, memo);
863+
if (!args)
864+
return NULL;
865+
result = PyObject_CallObject(st->deepcopy_obj, args);
866+
Py_DECREF(args);
867+
return result;
868+
}
869+
870+
841871
/*[clinic input]
842872
_elementtree.Element.__sizeof__ -> Py_ssize_t
843873

0 commit comments

Comments
 (0)