[Python-checkins] r65814 - python/trunk/Objects/stringlib/string_format.h

eric.smith python-checkins at python.org
Mon Aug 18 16:27:38 CEST 2008


Author: eric.smith
Date: Mon Aug 18 16:27:38 2008
New Revision: 65814

Log:
Backport of r63826.

Optimization of str.format() for cases with str, unicode, int, long,
and float 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 there's a complication in 2.6 with int, long, and float
because they always expect str format_specs.  So in the unicode
version of this optimization, just check for unicode objects.  int,
float, long, and str can be added later, if needed.


Modified:
   python/trunk/Objects/stringlib/string_format.h

Modified: python/trunk/Objects/stringlib/string_format.h
==============================================================================
--- python/trunk/Objects/stringlib/string_format.h	(original)
+++ python/trunk/Objects/stringlib/string_format.h	Mon Aug 18 16:27:38 2008
@@ -483,13 +483,49 @@
 {
     int ok = 0;
     PyObject *result = NULL;
+    PyObject *format_spec_object = NULL;
+    PyObject *(*formatter)(PyObject *, STRINGLIB_CHAR *, Py_ssize_t) = 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 STRINGLIB_IS_UNICODE
+    if (PyUnicode_CheckExact(fieldobj))
+	formatter = _PyUnicode_FormatAdvanced;
+    /* Unfortunately, there's a problem with checking for int, long,
+       and float here.  If we're being included as unicode, their
+       formatters expect string format_spec args.  For now, just skip
+       this optimization for unicode.  This could be fixed, but it's a
+       hassle. */
+#else
+    if (PyString_CheckExact(fieldobj))
+	formatter = _PyBytes_FormatAdvanced;
+    else if (PyInt_CheckExact(fieldobj))
+	formatter =_PyInt_FormatAdvanced;
+    else if (PyLong_CheckExact(fieldobj))
+	formatter =_PyLong_FormatAdvanced;
+    else if (PyFloat_CheckExact(fieldobj))
+	formatter = _PyFloat_FormatAdvanced;
+#endif
 
-    /* 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;
+    if (formatter) {
+	/* we know exactly which formatter will be called when __format__ is
+	   looked up, so call it directly, instead. */
+	result = formatter(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;
 
-    result = PyObject_Format(fieldobj, format_spec_object);
+	result = PyObject_Format(fieldobj, format_spec_object);
+    }
     if (result == NULL)
         goto done;
 
@@ -512,7 +548,7 @@
     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;
 }


More information about the Python-checkins mailing list