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;
}