diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2017-02-02 09:12:47 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2017-02-02 09:12:47 (GMT) |
commit | bee09aecc2c317fd3488b819ab88a13e0755189e (patch) | |
tree | 7a7efc93b0be362f0bace2153092feeb9b32204b /Modules/_pickle.c | |
parent | bb19bf275b465b8a17da51b6365f9d2800921a05 (diff) | |
download | cpython-bee09aecc2c317fd3488b819ab88a13e0755189e.zip cpython-bee09aecc2c317fd3488b819ab88a13e0755189e.tar.gz cpython-bee09aecc2c317fd3488b819ab88a13e0755189e.tar.bz2 |
Issue #29368: The extend() method is now called instead of the append()
method when unpickle collections.deque and other list-like objects.
This can speed up unpickling to 2 times.
Diffstat (limited to 'Modules/_pickle.c')
-rw-r--r-- | Modules/_pickle.c | 60 |
1 files changed, 41 insertions, 19 deletions
diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 19f94dc..996d16e 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -5807,7 +5807,9 @@ static int do_append(UnpicklerObject *self, Py_ssize_t x) { PyObject *value; + PyObject *slice; PyObject *list; + PyObject *result; Py_ssize_t len, i; len = Py_SIZE(self->stack); @@ -5818,8 +5820,7 @@ do_append(UnpicklerObject *self, Py_ssize_t x) list = self->stack->data[x - 1]; - if (PyList_Check(list)) { - PyObject *slice; + if (PyList_CheckExact(list)) { Py_ssize_t list_len; int ret; @@ -5832,27 +5833,48 @@ do_append(UnpicklerObject *self, Py_ssize_t x) return ret; } else { - PyObject *append_func; - _Py_IDENTIFIER(append); - - append_func = _PyObject_GetAttrId(list, &PyId_append); - if (append_func == NULL) - return -1; - for (i = x; i < len; i++) { - PyObject *result; - - value = self->stack->data[i]; - result = _Pickle_FastCall(append_func, value); - if (result == NULL) { - Pdata_clear(self->stack, i + 1); - Py_SIZE(self->stack) = x; - Py_DECREF(append_func); + PyObject *extend_func; + _Py_IDENTIFIER(extend); + + extend_func = _PyObject_GetAttrId(list, &PyId_extend); + if (extend_func != NULL) { + slice = Pdata_poplist(self->stack, x); + if (!slice) { + Py_DECREF(extend_func); return -1; } + result = _Pickle_FastCall(extend_func, slice); + Py_DECREF(slice); + Py_DECREF(extend_func); + if (result == NULL) + return -1; Py_DECREF(result); } - Py_SIZE(self->stack) = x; - Py_DECREF(append_func); + else { + PyObject *append_func; + _Py_IDENTIFIER(append); + + /* Even if the PEP 307 requires extend() and append() methods, + fall back on append() if the object has no extend() method + for backward compatibility. */ + PyErr_Clear(); + append_func = _PyObject_GetAttrId(list, &PyId_append); + if (append_func == NULL) + return -1; + for (i = x; i < len; i++) { + value = self->stack->data[i]; + result = _Pickle_FastCall(append_func, value); + if (result == NULL) { + Pdata_clear(self->stack, i + 1); + Py_SIZE(self->stack) = x; + Py_DECREF(append_func); + return -1; + } + Py_DECREF(result); + } + Py_SIZE(self->stack) = x; + Py_DECREF(append_func); + } } return 0; |