diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 5ebcfef6143..865dc1aa34e 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3341,6 +3341,114 @@ test_critical_sections(PyObject *module, PyObject *Py_UNUSED(args)) Py_RETURN_NONE; } +static PyObject * +bench_bytearray(PyObject *Py_UNUSED(module), PyObject *args) +{ + Py_ssize_t loops; + if (!PyArg_ParseTuple(args, "n", &loops)) { + return NULL; + } + + PyObject *str_var = PyBytes_FromString("var"); + PyObject *str_equal = PyBytes_FromString("="); + PyObject *str_string_value = PyBytes_FromString("string value"); + if (str_var == NULL || str_equal == NULL || str_string_value == NULL) { + Py_XDECREF(str_var); + Py_XDECREF(str_equal); + Py_XDECREF(str_string_value); + return NULL; + } + + PyTime_t t1; + (void)PyTime_PerfCounterRaw(&t1); + + for (Py_ssize_t i=0; i < loops; i++) { + PyObject *bytearray = PyByteArray_FromStringAndSize("", 0); + if (bytearray == NULL) { + return NULL; + } + + PyObject *res; + res = PySequence_InPlaceConcat(bytearray, str_var); + if (res == NULL) { + return NULL; + } + Py_DECREF(res); + + res = PySequence_InPlaceConcat(bytearray, str_equal); + if (res == NULL) { + return NULL; + } + Py_DECREF(res); + + res = PySequence_InPlaceConcat(bytearray, str_string_value); + if (res == NULL) { + return NULL; + } + Py_DECREF(res); + + char *str = PyByteArray_AsString(bytearray); + Py_ssize_t size = PyByteArray_Size(bytearray); + PyObject *bytes = PyBytes_FromStringAndSize(str, size); + Py_DECREF(bytearray); + assert(bytes != NULL); + Py_DECREF(bytes); + } + + PyTime_t t2; + (void)PyTime_PerfCounterRaw(&t2); + + Py_DECREF(str_var); + Py_DECREF(str_equal); + Py_DECREF(str_string_value); + + return PyFloat_FromDouble(PyTime_AsSecondsDouble(t2 - t1)); +} + + +static PyObject * +bench_writer(PyObject *Py_UNUSED(module), PyObject *args) +{ + Py_ssize_t loops; + if (!PyArg_ParseTuple(args, "n", &loops)) { + return NULL; + } + + PyTime_t t1; + (void)PyTime_PerfCounterRaw(&t1); + + for (Py_ssize_t i=0; i < loops; i++) { + char *str; + // 5 = len("var=x") + PyBytesWriter *writer = PyBytesWriter_Create(5, &str); + if (writer == NULL) { + return NULL; + } + + memcpy(str, "var", 3); + str += 3; + *str++ = '='; + + if (PyBytesWriter_Prepare(writer, &str, 12) < 0) { + PyBytesWriter_Discard(writer); + return NULL; + } + + memcpy(str, "string value", 12); + str += 12; + + PyObject *bytes = PyBytesWriter_Finish(writer, str); + assert(bytes != NULL); + Py_DECREF(bytes); + } + + PyTime_t t2; + (void)PyTime_PerfCounterRaw(&t2); + + return PyFloat_FromDouble(PyTime_AsSecondsDouble(t2 - t1)); +} + + static PyMethodDef TestMethods[] = { {"set_errno", set_errno, METH_VARARGS}, {"test_config", test_config, METH_NOARGS}, @@ -3483,6 +3591,8 @@ static PyMethodDef TestMethods[] = { {"test_weakref_capi", test_weakref_capi, METH_NOARGS}, {"function_set_warning", function_set_warning, METH_NOARGS}, {"test_critical_sections", test_critical_sections, METH_NOARGS}, + {"bench_bytearray", bench_bytearray, METH_VARARGS}, + {"bench_writer", bench_writer, METH_VARARGS}, {NULL, NULL} /* sentinel */ };