Skip to content

Commit 2d81eae

Browse files
gh-72113: Speed up constructing ctypes arrays (GH-159247)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
1 parent 42c7e26 commit 2d81eae

2 files changed

Lines changed: 21 additions & 0 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Speed up creating a :mod:`ctypes` array from initializers, such as
2+
``(c_int * 3)(1, 2, 3)``, by roughly 3x.

‎Modules/_ctypes/_ctypes.c‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4961,6 +4961,9 @@ static PyType_Spec pycunion_spec = {
49614961
/*
49624962
PyCArray_Type
49634963
*/
4964+
static int Array_ass_item_lock_held(PyObject *, Py_ssize_t, PyObject *);
4965+
static int Array_ass_subscript(PyObject *, PyObject *, PyObject *);
4966+
49644967
static int
49654968
Array_init(PyObject *self, PyObject *args, PyObject *kw)
49664969
{
@@ -4973,6 +4976,22 @@ Array_init(PyObject *self, PyObject *args, PyObject *kw)
49734976
return -1;
49744977
}
49754978
n = PyTuple_GET_SIZE(args);
4979+
4980+
/* Optimization: If the type doesn't override __setitem__, we can store the
4981+
* items directly (see gh-72113). */
4982+
PyMappingMethods *mp = Py_TYPE(self)->tp_as_mapping;
4983+
if (mp != NULL && mp->mp_ass_subscript == Array_ass_subscript) {
4984+
int result = 0;
4985+
Py_BEGIN_CRITICAL_SECTION(self);
4986+
for (i = 0; result >= 0 && i < n; ++i) {
4987+
PyObject *v = PyTuple_GET_ITEM(args, i);
4988+
assert(v != NULL);
4989+
result = Array_ass_item_lock_held(self, i, v);
4990+
}
4991+
Py_END_CRITICAL_SECTION();
4992+
return result;
4993+
}
4994+
49764995
for (i = 0; i < n; ++i) {
49774996
PyObject *v;
49784997
v = PyTuple_GET_ITEM(args, i);

0 commit comments

Comments
 (0)