Issue #25869: Optimized deepcopying ElementTree; it is now 20 times faster.

This commit is contained in:
Serhiy Storchaka 2015-12-21 12:57:27 +02:00
parent 22adf2ac02
commit 060ed718ce
2 changed files with 56 additions and 24 deletions

View File

@ -115,6 +115,8 @@ Core and Builtins
Library Library
------- -------
- Issue #25869: Optimized deepcopying ElementTree; it is now 20 times faster.
- Issue #25873: Optimized iterating ElementTree. Iterating elements - Issue #25873: Optimized iterating ElementTree. Iterating elements
Element.iter() is now 40% faster, iterating text Element.itertext() Element.iter() is now 40% faster, iterating text Element.itertext()
is now up to 2.5 times faster. is now up to 2.5 times faster.

View File

@ -128,30 +128,6 @@ elementtree_free(void *m)
/* helpers */ /* 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*) LOCAL(PyObject*)
list_join(PyObject* list) list_join(PyObject* list)
{ {
@ -748,6 +724,9 @@ _elementtree_Element___copy___impl(ElementObject *self)
return (PyObject*) element; return (PyObject*) element;
} }
/* Helper for a deep copy. */
LOCAL(PyObject *) deepcopy(PyObject *, PyObject *);
/*[clinic input] /*[clinic input]
_elementtree.Element.__deepcopy__ _elementtree.Element.__deepcopy__
@ -838,6 +817,57 @@ _elementtree_Element___deepcopy__(ElementObject *self, PyObject *memo)
return NULL; 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] /*[clinic input]
_elementtree.Element.__sizeof__ -> Py_ssize_t _elementtree.Element.__sizeof__ -> Py_ssize_t