https://github.com/python/cpython/commit/1955eb3ec065bda56ed74c7473f293b8f21a22b2
commit: 1955eb3ec065bda56ed74c7473f293b8f21a22b2
branch: main
author: Cody Maloney <[email protected]>
committer: cmaloney <[email protected]>
date: 2026-11-07T17:06:25-08:00
summary:

gh-160725: Speed up print() by using string constants and doing faster binding 
(#160727)

Pass the cached ' ' and '\n' strings for the default sep and end directly, 
instead of converting them from C strings with PyFile_WriteString(), which runs 
strlen() and the UTF-8 decoder on every call to get back the same cached string.

Rebinding file.write during print() keeps working as before. GH-160803 
significantly lowered binding cost. Could save ~5ns/call on x64 linux by 
binding only once, but that is left for work in 
https://discuss.python.org/t/make-print-use-a-single-write-call/109886

| Benchmark                                      | main    | this PR            
   |
|------------------------------------------------|:-------:|:---------------------:|
| print(file=devnull)                            | 51.2 ns | 47.4 ns: 1.08x 
faster |
| print('hello world', file=devnull)             | 81.0 ns | 79.2 ns: 1.02x 
faster |
| print('a', 1, 2.5, file=devnull)               | 281 ns  | 278 ns: 1.01x 
faster  |
| print('a', 'b', sep='-', end='', file=devnull) | 124 ns  | 126 ns: 1.02x 
slower  |

Benchmark hidden because not significant (1): print(*ten_ints, file=devnull)

Co-authored-by: Claude Opus 5.5 <[email protected]>

files:
M Python/bltinmodule.c

diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index c8e58f77d1d375..72f2e356c34f7c 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -2240,7 +2240,7 @@ builtin_print_impl(PyObject *module, PyObject * const 
*objects,
                    PyObject *file, int flush)
 /*[clinic end generated code: output=38d8def56c837bcc input=ff35cb3d59ee8115]*/
 {
-    int i, err;
+    int i;
 
     if (file == Py_None) {
         file = PySys_GetAttr(&_Py_ID(stdout));
@@ -2259,7 +2259,7 @@ builtin_print_impl(PyObject *module, PyObject * const 
*objects,
     }
 
     if (sep == Py_None) {
-        sep = NULL;
+        sep = _Py_LATIN1_CHR(' ');
     }
     else if (sep && !PyUnicode_Check(sep)) {
         PyErr_Format(PyExc_TypeError,
@@ -2269,7 +2269,7 @@ builtin_print_impl(PyObject *module, PyObject * const 
*objects,
         return NULL;
     }
     if (end == Py_None) {
-        end = NULL;
+        end = _Py_LATIN1_CHR('\n');
     }
     else if (end && !PyUnicode_Check(end)) {
         PyErr_Format(PyExc_TypeError,
@@ -2280,32 +2280,16 @@ builtin_print_impl(PyObject *module, PyObject * const 
*objects,
     }
 
     for (i = 0; i < objects_length; i++) {
-        if (i > 0) {
-            if (sep == NULL) {
-                err = PyFile_WriteString(" ", file);
-            }
-            else {
-                err = PyFile_WriteObject(sep, file, Py_PRINT_RAW);
-            }
-            if (err) {
-                Py_DECREF(file);
-                return NULL;
-            }
+        if (i > 0 && PyFile_WriteObject(sep, file, Py_PRINT_RAW) < 0) {
+            Py_DECREF(file);
+            return NULL;
         }
-        err = PyFile_WriteObject(objects[i], file, Py_PRINT_RAW);
-        if (err) {
+        if (PyFile_WriteObject(objects[i], file, Py_PRINT_RAW) < 0) {
             Py_DECREF(file);
             return NULL;
         }
     }
-
-    if (end == NULL) {
-        err = PyFile_WriteString("\n", file);
-    }
-    else {
-        err = PyFile_WriteObject(end, file, Py_PRINT_RAW);
-    }
-    if (err) {
+    if (PyFile_WriteObject(end, file, Py_PRINT_RAW) < 0) {
         Py_DECREF(file);
         return NULL;
     }

_______________________________________________
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