diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 20107f2257..18d3fd7dcd 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5449,7 +5449,46 @@ test_fatal_error(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject * +test_bench_incref(PyObject *module, PyObject *args) +{ + Py_ssize_t nloop; + PyObject *list; + + if (PyArg_ParseTuple(args, "nO!", &nloop, &PyList_Type, &list) < 0) { + return NULL; + } + + Py_ssize_t len = PyList_Size(list); + struct timespec start; + clock_gettime(CLOCK_MONOTONIC, &start); + + for (Py_ssize_t loop=0; loop < nloop; loop++) { + PyObject **dst = PyMem_Malloc(len * sizeof(PyObject*)); + if (dst == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (Py_ssize_t i=0; i < len; i++) { + PyObject *item = PyList_GetItem(list, i); + Py_INCREF(item); + dst[i] = item; + } + for (Py_ssize_t i=0; i < len; i++) { + PyObject *item = dst[i]; + Py_DECREF(item); + } + PyMem_Free(dst); + } + + struct timespec stop; + clock_gettime(CLOCK_MONOTONIC, &stop); + + int64_t a = start.tv_sec * 1000000000 + start.tv_nsec; + int64_t b = stop.tv_sec * 1000000000 + stop.tv_nsec; + return PyFloat_FromDouble((b - a) / 1e9); +} static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -5719,6 +5758,7 @@ static PyMethodDef TestMethods[] = { {"test_refcount", test_refcount, METH_NOARGS}, {"fatal_error", test_fatal_error, METH_VARARGS, PyDoc_STR("fatal_error(message, release_gil=False): call Py_FatalError(message)")}, + {"bench_incref", test_bench_incref, METH_VARARGS, NULL}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c index 883c8a9b5e..8d3e9b1574 100644 --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -274,7 +274,46 @@ xx_new(PyObject *module, PyObject *Py_UNUSED(unused)) return (PyObject *)rv; } +static PyObject * +xx_bench_incref(PyObject *module, PyObject *args) +{ + Py_ssize_t nloop; + PyObject *list; + + if (PyArg_ParseTuple(args, "nO!", &nloop, &PyList_Type, &list) < 0) { + return NULL; + } + + Py_ssize_t len = PyList_Size(list); + + struct timespec start; + clock_gettime(CLOCK_MONOTONIC, &start); + + for (Py_ssize_t loop=0; loop < nloop; loop++) { + PyObject **dst = PyMem_Malloc(len * sizeof(PyObject*)); + if (dst == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (Py_ssize_t i=0; i < len; i++) { + PyObject *item = PyList_GetItem(list, i); + Py_INCREF(item); + dst[i] = item; + } + for (Py_ssize_t i=0; i < len; i++) { + PyObject *item = dst[i]; + Py_DECREF(item); + } + PyMem_Free(dst); + } + + struct timespec stop; + clock_gettime(CLOCK_MONOTONIC, &stop); + int64_t a = start.tv_sec * 1000000000 + start.tv_nsec; + int64_t b = stop.tv_sec * 1000000000 + stop.tv_nsec; + return PyFloat_FromDouble((b - a) / 1e9); +} /* List of functions defined in the module */ @@ -283,6 +322,8 @@ static PyMethodDef xx_methods[] = { xx_foo_doc}, {"new", xx_new, METH_NOARGS, PyDoc_STR("new() -> new Xx object")}, + {"bench_incref", xx_bench_incref, METH_VARARGS, + PyDoc_STR("new() -> new Xx object")}, {NULL, NULL} /* sentinel */ };