Skip to content

Make copy.deepcopy faster for slice objects #100817

Closed as not planned
Closed as not planned
@sobolevn

Description

@sobolevn

slice

Right now slice objects are deepcopied using __reduce__ defined as:

static PyObject *
slice_reduce(PySliceObject* self, PyObject *Py_UNUSED(ignored))
{
return Py_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

def deepcopy(x, memo=None, _nil=[]):
"""Deep copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
"""
if memo is None:
memo = {}
d = id(x)
y = memo.get(d, _nil)
if y is not _nil:
return y
cls = type(x)
copier = _deepcopy_dispatch.get(cls)
if copier is not None:
y = copier(x, memo)
else:
if issubclass(cls, type):
y = _deepcopy_atomic(x, memo)
else:
copier = getattr(x, "__deepcopy__", None)
if copier is not None:
y = copier(memo)
else:
reductor = dispatch_table.get(cls)
if reductor:
rv = reductor(x)
else:
reductor = getattr(x, "__reduce_ex__", None)
if reductor is not None:
rv = reductor(4)
else:
reductor = getattr(x, "__reduce__", None)
if reductor:
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