Typical perf output of ralloc's printf-like functions looks like that: 0,14% ralloc_vasprintf_rewrite_tail 0,06% printf_length 0,05% __vsnprintf_chk 0,02% resize 0,01% __vsnprintf_chk@plt
They spend most of the time inside of libc's formatted i/o functions they call twice -- first inside of printf_length() to calculate resulting string length, then resize the buffer, then to actually print the string to the resized buffer. Try to avoid double vsnprintf() printing the string to a large enough temporary buffer. If the string wasn't trimmed, just memcpy() it to the output without printing it again. --- src/util/ralloc.c | 57 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/util/ralloc.c b/src/util/ralloc.c index 980e4e4..df2b1d8 100644 --- a/src/util/ralloc.c +++ b/src/util/ralloc.c @@ -429,14 +429,18 @@ ralloc_asprintf(const void *ctx, const char *fmt, ...) return ptr; } +#define PRINTF_BUF_SIZE 128 + /* Return the length of the string that would be generated by a printf-style - * format and argument list, not including the \0 byte. + * format and argument list, not including the \0 byte. Print the string to + * PRINTF_BUF_SIZE-sized buffer and set fully_printed to true, if the entire + * string was printed to the buf. */ static size_t -printf_length(const char *fmt, va_list untouched_args) +printf_length(const char *fmt, char* buf, bool *fully_printed, + va_list untouched_args) { int size; - char junk; /* Make a copy of the va_list so the original caller can still use it */ va_list args; @@ -447,9 +451,10 @@ printf_length(const char *fmt, va_list untouched_args) * if the number of characters to write is greater than count. */ size = _vscprintf(fmt, args); - (void)junk; + *fully_printed = false; #else - size = vsnprintf(&junk, 1, fmt, args); + size = vsnprintf(buf, PRINTF_BUF_SIZE, fmt, args); + *fully_printed = size <= (PRINTF_BUF_SIZE - 1); #endif assert(size >= 0); @@ -461,11 +466,17 @@ printf_length(const char *fmt, va_list untouched_args) char * ralloc_vasprintf(const void *ctx, const char *fmt, va_list args) { - size_t size = printf_length(fmt, args) + 1; + char buf[PRINTF_BUF_SIZE]; + bool fully_printed; + size_t size = printf_length(fmt, buf, &fully_printed, args) + 1; char *ptr = ralloc_size(ctx, size); - if (ptr != NULL) - vsnprintf(ptr, size, fmt, args); + if (ptr != NULL) { + if (fully_printed) + memcpy(ptr, buf, size); + else + vsnprintf(ptr, size, fmt, args); + } return ptr; } @@ -507,6 +518,8 @@ ralloc_vasprintf_rewrite_tail(char **str, size_t *start, const char *fmt, { size_t new_length; char *ptr; + char buf[PRINTF_BUF_SIZE]; + bool fully_printed; assert(str != NULL); @@ -517,13 +530,16 @@ ralloc_vasprintf_rewrite_tail(char **str, size_t *start, const char *fmt, return true; } - new_length = printf_length(fmt, args); + new_length = printf_length(fmt, buf, &fully_printed, args); ptr = resize(*str, *start + new_length + 1); if (unlikely(ptr == NULL)) return false; - vsnprintf(ptr + *start, new_length + 1, fmt, args); + if (fully_printed) + memcpy(ptr + *start, buf, new_length + 1); + else + vsnprintf(ptr + *start, new_length + 1, fmt, args); *str = ptr; *start += new_length; return true; @@ -788,11 +804,17 @@ linear_asprintf(void *parent, const char *fmt, ...) char * linear_vasprintf(void *parent, const char *fmt, va_list args) { - unsigned size = printf_length(fmt, args) + 1; + char buf[PRINTF_BUF_SIZE]; + bool fully_printed; + unsigned size = printf_length(fmt, buf, &fully_printed, args) + 1; char *ptr = linear_alloc_child(parent, size); - if (ptr != NULL) - vsnprintf(ptr, size, fmt, args); + if (ptr != NULL) { + if (fully_printed) + memcpy(ptr, buf, size); + else + vsnprintf(ptr, size, fmt, args); + } return ptr; } @@ -835,6 +857,8 @@ linear_vasprintf_rewrite_tail(void *parent, char **str, size_t *start, { size_t new_length; char *ptr; + char buf[PRINTF_BUF_SIZE]; + bool fully_printed; assert(str != NULL); @@ -844,13 +868,16 @@ linear_vasprintf_rewrite_tail(void *parent, char **str, size_t *start, return true; } - new_length = printf_length(fmt, args); + new_length = printf_length(fmt, buf, &fully_printed, args); ptr = linear_realloc(parent, *str, *start + new_length + 1); if (unlikely(ptr == NULL)) return false; - vsnprintf(ptr + *start, new_length + 1, fmt, args); + if (fully_printed) + memcpy(ptr + *start, buf, new_length + 1); + else + vsnprintf(ptr + *start, new_length + 1, fmt, args); *str = ptr; *start += new_length; return true; -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev