]> granicus.if.org Git - python/commitdiff
Optimization of str.format() for cases with unicode, long, and float
authorEric Smith <eric@trueblade.com>
Sat, 31 May 2008 01:40:08 +0000 (01:40 +0000)
committerEric Smith <eric@trueblade.com>
Sat, 31 May 2008 01:40:08 +0000 (01:40 +0000)
arguments.  This gives about 30% speed improvement for the simplest
(but most common) cases.  This patch skips the __format__ dispatch, and
also avoids creating an object to hold the format_spec.

Unfortunately, backporting this to 2.6 is going to be more challenging
due to str/unicode issues with format_spec.  I'll work on that next.

Then I'll spend some time profiling and see what that tells me.

Objects/stringlib/string_format.h

index 2e9c7efd4c14e68ffdb3da77a7e3580663c791ae..7e62af575fe88fdaead1983d163e64be6a84bc52 100644 (file)
@@ -483,13 +483,34 @@ render_field(PyObject *fieldobj, SubString *format_spec, OutputString *output)
 {
     int ok = 0;
     PyObject *result = NULL;
+    PyObject *format_spec_object = NULL;
+
+    STRINGLIB_CHAR* format_spec_start = format_spec->ptr ?
+           format_spec->ptr : NULL;
+    Py_ssize_t format_spec_len = format_spec->ptr ?
+           format_spec->end - format_spec->ptr : 0;
+
+    /* If we know the type exactly, skip the lookup of __format__ and just
+       call the formatter directly. */
+    if (PyUnicode_CheckExact(fieldobj))
+       result = _PyUnicode_FormatAdvanced(fieldobj, format_spec_start,
+                                       format_spec_len);
+    else if (PyLong_CheckExact(fieldobj))
+       result = _PyLong_FormatAdvanced(fieldobj, format_spec_start,
+                                       format_spec_len);
+    else if (PyFloat_CheckExact(fieldobj))
+       result = _PyFloat_FormatAdvanced(fieldobj, format_spec_start,
+                                        format_spec_len);
+    else {
+       /* We need to create an object out of the pointers we have, because
+          __format__ takes a string/unicode object for format_spec. */
+       format_spec_object = STRINGLIB_NEW(format_spec_start,
+                                          format_spec_len);
+       if (format_spec_object == NULL)
+           goto done;
 
-    /* we need to create an object out of the pointers we have */
-    PyObject *format_spec_object = SubString_new_object_or_empty(format_spec);
-    if (format_spec_object == NULL)
-        goto done;
-
-    result = PyObject_Format(fieldobj, format_spec_object);
+       result = PyObject_Format(fieldobj, format_spec_object);
+    }
     if (result == NULL)
         goto done;
 
@@ -512,7 +533,7 @@ render_field(PyObject *fieldobj, SubString *format_spec, OutputString *output)
     ok = output_data(output,
                      STRINGLIB_STR(result), STRINGLIB_LEN(result));
 done:
-    Py_DECREF(format_spec_object);
+    Py_XDECREF(format_spec_object);
     Py_XDECREF(result);
     return ok;
 }