https://github.com/python/cpython/commit/2d81eaeb1aacfa071273eb871e41a7d9793e6045
commit: 2d81eaeb1aacfa071273eb871e41a7d9793e6045
branch: main
author: Peter Bierma <[email protected]>
committer: ZeroIntensity <[email protected]>
date: 2026-10-19T14:59:37-04:00
summary:

gh-72113: Speed up constructing `ctypes` arrays (GH-159247)

Co-authored-by: Bénédikt Tran <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-10-12-12-00-00.gh-issue-72113.njkm8v.rst
M Modules/_ctypes/_ctypes.c

diff --git 
a/Misc/NEWS.d/next/Library/2026-10-12-12-00-00.gh-issue-72113.njkm8v.rst 
b/Misc/NEWS.d/next/Library/2026-10-12-12-00-00.gh-issue-72113.njkm8v.rst
new file mode 100644
index 000000000000000..9057f3246b3e2b7
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-12-12-00-00.gh-issue-72113.njkm8v.rst
@@ -0,0 +1,2 @@
+Speed up creating a :mod:`ctypes` array from initializers, such as
+``(c_int * 3)(1, 2, 3)``, by roughly 3x.
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index f0945e48aa3bf03..43f416c141fd8ad 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -4961,6 +4961,9 @@ static PyType_Spec pycunion_spec = {
 /*
   PyCArray_Type
 */
+static int Array_ass_item_lock_held(PyObject *, Py_ssize_t, PyObject *);
+static int Array_ass_subscript(PyObject *, PyObject *, PyObject *);
+
 static int
 Array_init(PyObject *self, PyObject *args, PyObject *kw)
 {
@@ -4973,6 +4976,22 @@ Array_init(PyObject *self, PyObject *args, PyObject *kw)
         return -1;
     }
     n = PyTuple_GET_SIZE(args);
+
+    /* Optimization: If the type doesn't override __setitem__, we can store the
+     * items directly (see gh-72113). */
+    PyMappingMethods *mp = Py_TYPE(self)->tp_as_mapping;
+    if (mp != NULL && mp->mp_ass_subscript == Array_ass_subscript) {
+        int result = 0;
+        Py_BEGIN_CRITICAL_SECTION(self);
+        for (i = 0; result >= 0 && i < n; ++i) {
+            PyObject *v = PyTuple_GET_ITEM(args, i);
+            assert(v != NULL);
+            result = Array_ass_item_lock_held(self, i, v);
+        }
+        Py_END_CRITICAL_SECTION();
+        return result;
+    }
+
     for (i = 0; i < n; ++i) {
         PyObject *v;
         v = PyTuple_GET_ITEM(args, i);

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to