The functions in the __mingw_printf family are very slow because of the 
getenv(”PRINTF_EXPONENT_DIGITS”) call that is made every time, even when that 
information isn’t actually needed.

Please consider this patch. It only calls getenv once, caching the result (as 
is traditionally done in libraries that use environment variables this way). It 
also only computes the minimum exponent digits when actually needed, at most 
once per format call.

With this patch, __mingw_sprintf(buf, ”x”) goes from being several orders of 
magnitude slower than the MSVCRT sprintf, to about 66% faster. You don’t see 
this kind of improvement every day.

--- mingw-w64-crt/stdio/mingw_pformat.c.orig    2015-03-31 20:27:41.000465100 
+0200
+++ mingw-w64-crt/stdio/mingw_pformat.c 2015-03-31 21:42:05.990919500 +0200
@@ -171,12 +171,17 @@
 static
 int __pformat_exponent_digits( void )
 {
-  char *exponent_digits = getenv( "PRINTF_EXPONENT_DIGITS" );
-  return ((exponent_digits != NULL) && ((unsigned)(*exponent_digits - '0') < 
3))
-    || (_get_output_format() & _TWO_DIGIT_EXPONENT)
-    ? 2
-    : 3
-    ;
+  /* Calling getenv is expensive; only do it once and cache the result. */
+  static int two_exp_digits_env = -1;
+  if (two_exp_digits_env == -1) {
+    const char *exponent_digits_env = getenv( "PRINTF_EXPONENT_DIGITS" );
+    two_exp_digits_env = exponent_digits_env != NULL
+                         && (unsigned)(*exponent_digits_env - '0') < 3;
+  }
+  return (two_exp_digits_env || (_get_output_format() & _TWO_DIGIT_EXPONENT))
+         ? 2
+         : 3
+         ;
 }
 #else
 /*
@@ -1222,6 +1227,8 @@
 
   /* Ensure that this is at least as many as the standard requirement.
    */
+  if (stream->expmin == -1)
+    stream->expmin = PFORMAT_MINEXP;
   if( exp_width < stream->expmin )
     exp_width = stream->expmin;
 
@@ -1817,7 +1824,8 @@
     (wchar_t)(0),                              /* leave it unspecified       */
     0,                                         /* zero output char count     */
     max,                                       /* establish output limit     */
-    PFORMAT_MINEXP                             /* exponent chars preferred   */
+    -1                                         /* exponent chars preferred;
+                                                   -1 means to be determined. 
*/
   };
 
   format_scan: while( (c = *fmt++) != 0 )
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to