Skip to content

Conversation

@vstinner
Copy link
Member

@vstinner vstinner commented May 22, 2024

Add fast paths for str, int and float object types.

Benchmark on %S and %R formats:

+----------------+--------+----------------------+
| Benchmark      | ref    | change               |
+================+========+======================+
| str()          | 654 ns | 556 ns: 1.18x faster |
+----------------+--------+----------------------+
| repr()         | 722 ns | 627 ns: 1.15x faster |
+----------------+--------+----------------------+
| Geometric mean | (ref)  | 1.16x faster         |
+----------------+--------+----------------------+

Add fast paths for str, int and float object types.

Benchmark on %S and %R formats:

+----------------+--------+----------------------+
| Benchmark      | ref    | change               |
+================+========+======================+
| str()          | 654 ns | 556 ns: 1.18x faster |
+----------------+--------+----------------------+
| repr()         | 722 ns | 627 ns: 1.15x faster |
+----------------+--------+----------------------+
| Geometric mean | (ref)  | 1.16x faster         |
+----------------+--------+----------------------+
@vstinner
Copy link
Member Author

Benchmark:

diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index f99ebf0dde..53d2a8e5f7 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3312,6 +3312,46 @@ function_set_warning(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
     Py_RETURN_NONE;
 }

+static PyObject *
+bench_str(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
+{
+    PyObject *abc = PyUnicode_FromString("abc");
+    assert(abc != NULL);
+    PyObject *intobj = PyLong_FromLong(123);
+    assert(intobj != NULL);
+    PyObject *floatobj = PyFloat_FromDouble(1.0);
+    assert(floatobj != NULL);
+
+    PyObject *res = PyUnicode_FromFormat(
+        "str: %S, int: %S, float: %S",
+        abc, intobj, floatobj);
+
+    Py_DECREF(abc);
+    Py_DECREF(intobj);
+    Py_DECREF(floatobj);
+    return res;
+}
+
+static PyObject *
+bench_repr(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
+{
+    PyObject *abc = PyUnicode_FromString("abc");
+    assert(abc != NULL);
+    PyObject *intobj = PyLong_FromLong(123);
+    assert(intobj != NULL);
+    PyObject *floatobj = PyFloat_FromDouble(1.0);
+    assert(floatobj != NULL);
+
+    PyObject *res = PyUnicode_FromFormat(
+        "str: %R, int: %R, float: %R",
+        abc, intobj, floatobj);
+
+    Py_DECREF(abc);
+    Py_DECREF(intobj);
+    Py_DECREF(floatobj);
+    return res;
+}
+
 static PyMethodDef TestMethods[] = {
     {"set_errno",               set_errno,                       METH_VARARGS},
     {"test_config",             test_config,                     METH_NOARGS},
@@ -3454,6 +3494,8 @@ static PyMethodDef TestMethods[] = {
     {"check_pyimport_addmodule", check_pyimport_addmodule, METH_VARARGS},
     {"test_weakref_capi", test_weakref_capi, METH_NOARGS},
     {"function_set_warning", function_set_warning, METH_NOARGS},
+    {"bench_str", bench_str, METH_NOARGS},
+    {"bench_repr", bench_repr, METH_NOARGS},
     {NULL, NULL} /* sentinel */
 };

Script:

import pyperf
import _testcapi
runner = pyperf.Runner()
runner.bench_func('str()', _testcapi.bench_str)
runner.bench_func('repr()', _testcapi.bench_repr)

@vstinner
Copy link
Member Author

@vstinner vstinner closed this May 22, 2024
@vstinner vstinner deleted the optim_object_str branch May 22, 2024 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant