Merge "10x printf speedup."

This commit is contained in:
Elliott Hughes 2017-11-03 23:11:06 +00:00 committed by Gerrit Code Review
commit c18f55ca2b
4 changed files with 78 additions and 76 deletions

View File

@ -196,3 +196,12 @@ static void BM_stdio_printf_d(benchmark::State& state) {
} }
} }
BIONIC_BENCHMARK(BM_stdio_printf_d); BIONIC_BENCHMARK(BM_stdio_printf_d);
static void BM_stdio_printf_1$s(benchmark::State& state) {
while (state.KeepRunning()) {
char buf[BUFSIZ];
snprintf(buf, sizeof(buf), "this is a more typical error message with detail: %1$s",
"No such file or directory");
}
}
BIONIC_BENCHMARK(BM_stdio_printf_1$s);

View File

@ -197,6 +197,9 @@
<fn> <fn>
<name>BM_stdio_printf_d</name> <name>BM_stdio_printf_d</name>
</fn> </fn>
<fn>
<name>BM_stdio_printf_1$s</name>
</fn>
<fn> <fn>
<name>BM_string_memcmp</name> <name>BM_string_memcmp</name>
<args>AT_ALIGNED_TWOBUF</args> <args>AT_ALIGNED_TWOBUF</args>

View File

@ -251,7 +251,6 @@ static int exponent(CharT* p0, int exp, int fmtch) {
#define MAXINT 0x1000 /* largest integer size (intmax_t) */ #define MAXINT 0x1000 /* largest integer size (intmax_t) */
int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) { int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) {
char* fmt; /* format string */
int ch; /* character from fmt */ int ch; /* character from fmt */
int n, n2; /* handy integers (short term usage) */ int n, n2; /* handy integers (short term usage) */
char* cp; /* handy char pointer (short term usage) */ char* cp; /* handy char pointer (short term usage) */
@ -261,7 +260,6 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) {
int width; /* width from format (%8d), or 0 */ int width; /* width from format (%8d), or 0 */
int prec; /* precision from format; <0 for N/A */ int prec; /* precision from format; <0 for N/A */
char sign; /* sign prefix (' ', '+', '-', or \0) */ char sign; /* sign prefix (' ', '+', '-', or \0) */
wchar_t wc;
mbstate_t ps; mbstate_t ps;
/* /*
* We can decompose the printed representation of floating * We can decompose the printed representation of floating
@ -316,10 +314,12 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) {
* below longer. * below longer.
*/ */
#define PADSIZE 16 /* pad chunk size */ #define PADSIZE 16 /* pad chunk size */
static char blanks[PADSIZE] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', static CHAR_TYPE blanks[PADSIZE] = {
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
static char zeroes[PADSIZE] = { '0', '0', '0', '0', '0', '0', '0', '0', };
'0', '0', '0', '0', '0', '0', '0', '0' }; static CHAR_TYPE zeroes[PADSIZE] = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
};
static const char xdigs_lower[] = "0123456789abcdef"; static const char xdigs_lower[] = "0123456789abcdef";
static const char xdigs_upper[] = "0123456789ABCDEF"; static const char xdigs_upper[] = "0123456789ABCDEF";
@ -444,17 +444,19 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) {
((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : (nextarg++, va_arg(ap, type))) ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : (nextarg++, va_arg(ap, type)))
_SET_ORIENTATION(fp, -1); _SET_ORIENTATION(fp, -1);
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
// Writing "" to a read only file returns EOF, not 0.
if (cantwrite(fp)) { if (cantwrite(fp)) {
errno = EBADF; errno = EBADF;
return (EOF); return EOF;
} }
/* optimise fprintf(stderr) (and other unbuffered Unix files) */ // Optimize writes to stderr and other unbuffered files).
if ((fp->_flags & (__SNBF | __SWR | __SRW)) == (__SNBF | __SWR) && fp->_file >= 0) if ((fp->_flags & (__SNBF | __SWR | __SRW)) == (__SNBF | __SWR) && fp->_file >= 0) {
return (__sbprintf(fp, fmt0, ap)); return (__sbprintf(fp, fmt0, ap));
}
fmt = (char*)fmt0; CHAR_TYPE* fmt = const_cast<CHAR_TYPE*>(fmt0);
argtable = NULL; argtable = NULL;
nextarg = 1; nextarg = 1;
va_copy(orgap, ap); va_copy(orgap, ap);
@ -469,25 +471,14 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) {
* Scan the format for conversions (`%' character). * Scan the format for conversions (`%' character).
*/ */
for (;;) { for (;;) {
cp = fmt; for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) continue;
while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
fmt += n;
if (wc == '%') {
fmt--;
break;
}
}
if (n < 0) {
ret = -1;
goto error;
}
if (fmt != cp) { if (fmt != cp) {
ptrdiff_t m = fmt - cp; ptrdiff_t m = fmt - cp;
if (m < 0 || m > INT_MAX - ret) goto overflow; if (m < 0 || m > INT_MAX - ret) goto overflow;
PRINT(cp, m); PRINT(cp, m);
ret += m; ret += m;
} }
if (n == 0) goto done; if (ch == '\0') goto done;
fmt++; /* skip over '%' */ fmt++; /* skip over '%' */
flags = 0; flags = 0;
@ -1062,12 +1053,10 @@ finish:
* used since we are attempting to make snprintf thread safe, and alloca is * used since we are attempting to make snprintf thread safe, and alloca is
* problematic since we have nested functions..) * problematic since we have nested functions..)
*/ */
static int __find_arguments(const char* fmt0, va_list ap, union arg** argtable, static int __find_arguments(const CHAR_TYPE* fmt0, va_list ap, union arg** argtable,
size_t* argtablesiz) { size_t* argtablesiz) {
char* fmt; /* format string */
int ch; /* character from fmt */ int ch; /* character from fmt */
int n, n2; /* handy integer (short term usage) */ int n, n2; /* handy integer (short term usage) */
char* cp; /* handy char pointer (short term usage) */
int flags; /* flags as above */ int flags; /* flags as above */
unsigned char* typetable; /* table of types */ unsigned char* typetable; /* table of types */
unsigned char stattypetable[STATIC_ARG_TBL_SIZE]; unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
@ -1075,8 +1064,6 @@ static int __find_arguments(const char* fmt0, va_list ap, union arg** argtable,
int tablemax; /* largest used index in table */ int tablemax; /* largest used index in table */
int nextarg; /* 1-based argument index */ int nextarg; /* 1-based argument index */
int ret = 0; /* return value */ int ret = 0; /* return value */
wchar_t wc;
mbstate_t ps;
/* /*
* Add an argument type to the table, expanding if necessary. * Add an argument type to the table, expanding if necessary.
@ -1135,28 +1122,20 @@ static int __find_arguments(const char* fmt0, va_list ap, union arg** argtable,
} else { \ } else { \
ADDTYPE(T_INT); \ ADDTYPE(T_INT); \
} }
fmt = (char*)fmt0; CHAR_TYPE* fmt = const_cast<CHAR_TYPE*>(fmt0);
CHAR_TYPE* cp;
typetable = stattypetable; typetable = stattypetable;
tablesize = STATIC_ARG_TBL_SIZE; tablesize = STATIC_ARG_TBL_SIZE;
tablemax = 0; tablemax = 0;
nextarg = 1; nextarg = 1;
memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE); memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
memset(&ps, 0, sizeof(ps));
/* /*
* Scan the format for conversions (`%' character). * Scan the format for conversions (`%' character).
*/ */
for (;;) { for (;;) {
cp = fmt; for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) continue;
while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) { if (ch == '\0') goto done;
fmt += n;
if (wc == '%') {
fmt--;
break;
}
}
if (n < 0) return (-1);
if (n == 0) goto done;
fmt++; /* skip over '%' */ fmt++; /* skip over '%' */
flags = 0; flags = 0;

View File

@ -277,7 +277,6 @@ static int exponent(CharT* p0, int exp, int fmtch) {
#define MAXINT 0x1000 /* largest integer size (intmax_t) */ #define MAXINT 0x1000 /* largest integer size (intmax_t) */
int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list ap) { int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list ap) {
wchar_t* fmt; /* format string */
wchar_t ch; /* character from fmt */ wchar_t ch; /* character from fmt */
int n, n2, n3; /* handy integers (short term usage) */ int n, n2, n3; /* handy integers (short term usage) */
wchar_t* cp; /* handy char pointer (short term usage) */ wchar_t* cp; /* handy char pointer (short term usage) */
@ -336,10 +335,12 @@ int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list a
* below longer. * below longer.
*/ */
#define PADSIZE 16 /* pad chunk size */ #define PADSIZE 16 /* pad chunk size */
static wchar_t blanks[PADSIZE] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', static CHAR_TYPE blanks[PADSIZE] = {
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
static wchar_t zeroes[PADSIZE] = { '0', '0', '0', '0', '0', '0', '0', '0', };
'0', '0', '0', '0', '0', '0', '0', '0' }; static CHAR_TYPE zeroes[PADSIZE] = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
};
static const char xdigs_lower[] = "0123456789abcdef"; static const char xdigs_lower[] = "0123456789abcdef";
static const char xdigs_upper[] = "0123456789ABCDEF"; static const char xdigs_upper[] = "0123456789ABCDEF";
@ -432,7 +433,10 @@ int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list a
int hold = nextarg; \ int hold = nextarg; \
if (argtable == NULL) { \ if (argtable == NULL) { \
argtable = statargtable; \ argtable = statargtable; \
__find_arguments(fmt0, orgap, &argtable, &argtablesiz); \ if (__find_arguments(fmt0, orgap, &argtable, &argtablesiz) == -1) { \
ret = -1; \
goto error; \
} \
} \ } \
nextarg = n2; \ nextarg = n2; \
val = GETARG(int); \ val = GETARG(int); \
@ -451,17 +455,19 @@ int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list a
((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : (nextarg++, va_arg(ap, type))) ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : (nextarg++, va_arg(ap, type)))
_SET_ORIENTATION(fp, 1); _SET_ORIENTATION(fp, 1);
/* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */
// Writing "" to a read only file returns EOF, not 0.
if (cantwrite(fp)) { if (cantwrite(fp)) {
errno = EBADF; errno = EBADF;
return (EOF); return EOF;
} }
/* optimise fwprintf(stderr) (and other unbuffered Unix files) */ // Optimize writes to stderr and other unbuffered files).
if ((fp->_flags & (__SNBF | __SWR | __SRW)) == (__SNBF | __SWR) && fp->_file >= 0) if ((fp->_flags & (__SNBF | __SWR | __SRW)) == (__SNBF | __SWR) && fp->_file >= 0) {
return (__sbprintf(fp, fmt0, ap)); return (__sbprintf(fp, fmt0, ap));
}
fmt = (wchar_t*)fmt0; CHAR_TYPE* fmt = const_cast<CHAR_TYPE*>(fmt0);
argtable = NULL; argtable = NULL;
nextarg = 1; nextarg = 1;
va_copy(orgap, ap); va_copy(orgap, ap);
@ -540,7 +546,10 @@ int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list a
nextarg = n; nextarg = n;
if (argtable == NULL) { if (argtable == NULL) {
argtable = statargtable; argtable = statargtable;
__find_arguments(fmt0, orgap, &argtable, &argtablesiz); if (__find_arguments(fmt0, orgap, &argtable, &argtablesiz) == -1) {
ret = -1;
goto error;
}
} }
goto rflag; goto rflag;
} }
@ -572,7 +581,10 @@ int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list a
nextarg = n; nextarg = n;
if (argtable == NULL) { if (argtable == NULL) {
argtable = statargtable; argtable = statargtable;
__find_arguments(fmt0, orgap, &argtable, &argtablesiz); if (__find_arguments(fmt0, orgap, &argtable, &argtablesiz) == -1) {
ret = -1;
goto error;
}
} }
goto rflag; goto rflag;
} }
@ -1037,12 +1049,10 @@ finish:
* used since we are attempting to make snprintf thread safe, and alloca is * used since we are attempting to make snprintf thread safe, and alloca is
* problematic since we have nested functions..) * problematic since we have nested functions..)
*/ */
static int __find_arguments(const wchar_t* fmt0, va_list ap, union arg** argtable, static int __find_arguments(const CHAR_TYPE* fmt0, va_list ap, union arg** argtable,
size_t* argtablesiz) { size_t* argtablesiz) {
wchar_t* fmt; /* format string */
int ch; /* character from fmt */ int ch; /* character from fmt */
int n, n2; /* handy integer (short term usage) */ int n, n2; /* handy integer (short term usage) */
wchar_t* cp; /* handy char pointer (short term usage) */
int flags; /* flags as above */ int flags; /* flags as above */
unsigned char* typetable; /* table of types */ unsigned char* typetable; /* table of types */
unsigned char stattypetable[STATIC_ARG_TBL_SIZE]; unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
@ -1108,7 +1118,8 @@ static int __find_arguments(const wchar_t* fmt0, va_list ap, union arg** argtabl
} else { \ } else { \
ADDTYPE(T_INT); \ ADDTYPE(T_INT); \
} }
fmt = (wchar_t*)fmt0; CHAR_TYPE* fmt = const_cast<CHAR_TYPE*>(fmt0);
CHAR_TYPE* cp;
typetable = stattypetable; typetable = stattypetable;
tablesize = STATIC_ARG_TBL_SIZE; tablesize = STATIC_ARG_TBL_SIZE;
tablemax = 0; tablemax = 0;