Sorry, just getting back to this now...

To recap, od using xprintf gives this throughput:
$ timeout 2 od -Ax -tx1z -v /dev/zero | pv >/dev/null # 1.58MB/s

There was lots of heap interaction going on,
and by using the attached patch (only illustrative, may leak,
is not thread safe, ...) to cache the PRINTF_PARSE result
it increases the throughput to 5.8MB/s

The rest of the time seems to be lost through the subsequent
call to snprintf, and I'm not sure how we can significantly improve that.
If we s/xprintf/printf/ in od.c for comparison, we get 10.7MB/s.

cheers,
Pádraig.
--- /home/padraig/git/gnulib/lib/vasnprintf.c	2011-01-17 07:47:38.000000000 +0000
+++ vasnprintf.c	2011-02-04 08:43:21.000000000 +0000
@@ -1745,21 +1747,38 @@
 VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
             const FCHAR_T *format, va_list args)
 {
-  DIRECTIVES d;
-  arguments a;
-
-  if (PRINTF_PARSE (format, &d, &a) < 0)
-    /* errno is already set.  */
-    return NULL;
+  static DIRECTIVES d;
+  static arguments a;
 
 #define CLEANUP() \
   free (d.dir);                                                         \
   if (a.arg)                                                            \
     free (a.arg);
 
+  static FCHAR_T *pformat;
+  if (pformat && strcmp (format, pformat) == 0)
+    {
+      /* Reuse previously parsed format.  */
+    }
+  else
+    {
+      if (pformat)
+        {
+          CLEANUP ();
+          free (pformat);
+          pformat = NULL;
+        }
+
+      if (PRINTF_PARSE (format, &d, &a) < 0)
+        /* errno is already set.  */
+        return NULL;
+
+      pformat = strdup (format);
+    }
+
+
   if (PRINTF_FETCHARGS (args, &a) < 0)
     {
-      CLEANUP ();
       errno = EINVAL;
       return NULL;
     }
@@ -2003,7 +2023,6 @@
                                     free (result);
                                   if (buf_malloced != NULL)
                                     free (buf_malloced);
-                                  CLEANUP ();
                                   errno = EILSEQ;
                                   return NULL;
                                 }
@@ -2028,7 +2047,6 @@
                                     free (result);
                                   if (buf_malloced != NULL)
                                     free (buf_malloced);
-                                  CLEANUP ();
                                   errno = EILSEQ;
                                   return NULL;
                                 }
@@ -2084,7 +2102,6 @@
                               free (result);
                             if (buf_malloced != NULL)
                               free (buf_malloced);
-                            CLEANUP ();
                             errno = saved_errno;
                             return NULL;
                           }
@@ -2131,7 +2148,6 @@
                                     free (result);
                                   if (buf_malloced != NULL)
                                     free (buf_malloced);
-                                  CLEANUP ();
                                   errno = EILSEQ;
                                   return NULL;
                                 }
@@ -2156,7 +2172,6 @@
                                     free (result);
                                   if (buf_malloced != NULL)
                                     free (buf_malloced);
-                                  CLEANUP ();
                                   errno = EILSEQ;
                                   return NULL;
                                 }
@@ -2212,7 +2227,6 @@
                               free (result);
                             if (buf_malloced != NULL)
                               free (buf_malloced);
-                            CLEANUP ();
                             errno = saved_errno;
                             return NULL;
                           }
@@ -2259,7 +2273,6 @@
                                     free (result);
                                   if (buf_malloced != NULL)
                                     free (buf_malloced);
-                                  CLEANUP ();
                                   errno = EILSEQ;
                                   return NULL;
                                 }
@@ -2284,7 +2297,6 @@
                                     free (result);
                                   if (buf_malloced != NULL)
                                     free (buf_malloced);
-                                  CLEANUP ();
                                   errno = EILSEQ;
                                   return NULL;
                                 }
@@ -2340,7 +2352,6 @@
                               free (result);
                             if (buf_malloced != NULL)
                               free (buf_malloced);
-                            CLEANUP ();
                             errno = saved_errno;
                             return NULL;
                           }
@@ -2492,7 +2503,6 @@
                                 free (result);
                               if (buf_malloced != NULL)
                                 free (buf_malloced);
-                              CLEANUP ();
                               errno = EILSEQ;
                               return NULL;
                             }
@@ -2528,7 +2538,6 @@
                                 free (result);
                               if (buf_malloced != NULL)
                                 free (buf_malloced);
-                              CLEANUP ();
                               errno = EILSEQ;
                               return NULL;
                             }
@@ -2660,7 +2669,6 @@
                                 free (result);
                               if (buf_malloced != NULL)
                                 free (buf_malloced);
-                              CLEANUP ();
                               errno = EILSEQ;
                               return NULL;
                             }
@@ -2705,7 +2713,6 @@
                                 free (result);
                               if (buf_malloced != NULL)
                                 free (buf_malloced);
-                              CLEANUP ();
                               errno = EILSEQ;
                               return NULL;
                             }
@@ -2774,7 +2781,6 @@
                         free (result);
                       if (buf_malloced != NULL)
                         free (buf_malloced);
-                      CLEANUP ();
                       errno = saved_errno;
                       return NULL;
                     }
@@ -2865,7 +2871,6 @@
                                 free (result);
                               if (buf_malloced != NULL)
                                 free (buf_malloced);
-                              CLEANUP ();
                               errno = EILSEQ;
                               return NULL;
                             }
@@ -5166,7 +5171,6 @@
                           free (result);
                         if (buf_malloced != NULL)
                           free (buf_malloced);
-                        CLEANUP ();
                         errno =
                           (saved_errno != 0
                            ? saved_errno
@@ -5313,7 +5317,6 @@
                               free (result);
                             if (buf_malloced != NULL)
                               free (buf_malloced);
-                            CLEANUP ();
                             errno = saved_errno;
                             return NULL;
                           }
@@ -5530,7 +5533,6 @@
 
     if (buf_malloced != NULL)
       free (buf_malloced);
-    CLEANUP ();
     *lengthp = length;
     /* Note that we can produce a big string of a length > INT_MAX.  POSIX
        says that snprintf() fails with errno = EOVERFLOW in this case, but
@@ -5544,7 +5546,6 @@
       free (result);
     if (buf_malloced != NULL)
       free (buf_malloced);
-    CLEANUP ();
     errno = EOVERFLOW;
     return NULL;
 #endif
@@ -5555,7 +5556,6 @@
     if (buf_malloced != NULL)
       free (buf_malloced);
   out_of_memory_1:
-    CLEANUP ();
     errno = ENOMEM;
     return NULL;
   }

Reply via email to