Skip to content

Make copy.deepcopy faster for slice objects#100817

@sobolevn

Description

@sobolevn

slice

Right now slice objects are deepcopied using __reduce__ defined as:

staticPyObject*
slice_reduce(PySliceObject*self, PyObject*Py_UNUSED(ignored))
{
returnPy_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
}

It is one of last branches of deepcopy logic:

cpython/Lib/copy.py

Lines 120 to 157 in 26ff436

defdeepcopy(x, memo=None, _nil=[]):
"""Deep copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
"""
ifmemoisNone:
memo={}
d=id(x)
y=memo.get(d, _nil)
ifyisnot_nil:
returny
cls=type(x)
copier=_deepcopy_dispatch.get(cls)
ifcopierisnotNone:
y=copier(x, memo)
else:
ifissubclass(cls, type):
y=_deepcopy_atomic(x, memo)
else:
copier=getattr(x, "__deepcopy__", None)
ifcopierisnotNone:
y=copier(memo)
else:
reductor=dispatch_table.get(cls)
ifreductor:
rv=reductor(x)
else:
reductor=getattr(x, "__reduce_ex__", None)
ifreductorisnotNone:
rv=reductor(4)
else:
reductor=getattr(x, "__reduce__", None)
ifreductor:
rv=reductor()

But, since slice is an immutable type without nested structures, we can optimize its deepcopy as:

d[slice] =_deepcopy_atomic

Before:

» pyperf timeit --setup 'from copy import deepcopy; s = slice(1,10,2)' 'deepcopy(s)' ..................... Mean +- std dev: 3.46 us +- 0.18 us 

After:

» pyperf timeit --setup 'from copy import deepcopy; s = slice(1,10,2)' 'deepcopy(s)' ..................... Mean +- std dev: 277 ns +- 3 ns 

Looks like a good speedup for just a single line!
Noticed while working on #100815

PR is incoming.

Linked PRs

Metadata

Metadata

Assignees

Labels

performancePerformance or resource usagetype-featureA feature request or enhancement

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions