bpo-45831: _Py_DumpASCII() uses a single write() call if possible (GH-29596) (GH-29598)

If the string is ASCII only and doesn't need to escape characters,
write the whole string with a single write() syscall.
(cherry picked from commit b919d8105c4d77f00509b6d3ab2073f09db640de)

Co-authored-by: Victor Stinner <vstinner@python.org>
diff --git a/Python/traceback.c b/Python/traceback.c
index 284c181..7d6f7f4 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -717,6 +717,26 @@ _Py_DumpASCII(int fd, PyObject *text)
         truncated = 0;
     }
 
+    // Is an ASCII string?
+    if (ascii->state.ascii) {
+        assert(kind == PyUnicode_1BYTE_KIND);
+        char *str = data;
+
+        int need_escape = 0;
+        for (i=0; i < size; i++) {
+            ch = str[i];
+            if (!(' ' <= ch && ch <= 126)) {
+                need_escape = 1;
+                break;
+            }
+        }
+        if (!need_escape) {
+            // The string can be written with a single write() syscall
+            _Py_write_noraise(fd, str, size);
+            goto done;
+        }
+    }
+
     for (i=0; i < size; i++) {
         if (kind != PyUnicode_WCHAR_KIND)
             ch = PyUnicode_READ(kind, data, i);
@@ -740,6 +760,8 @@ _Py_DumpASCII(int fd, PyObject *text)
             _Py_DumpHexadecimal(fd, ch, 8);
         }
     }
+
+done:
     if (truncated) {
         PUTS(fd, "...");
     }