From a8ebc3dcf541c7b5a7d7e0e315dea432dcab7279 Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Fri, 8 Apr 2016 09:38:54 -0700 Subject: [PATCH] Wmem: Use the native v*printf routines on Windows. GLib's v*printf routines are close to unreasonably slow on Windows. Use the native CRT routines in wmem_strdup_vprintf and wmem_strbuf_append_vprintf on that platform. Change-Id: I5e94aa6fe47434e5a18f3a4d5b6b24ebe71499c1 Reviewed-on: https://code.wireshark.org/review/14868 Reviewed-by: Evan Huus Reviewed-by: Anders Broman --- epan/wmem/wmem_strbuf.c | 36 ++++++++++++++++++++++++++++++++++++ epan/wmem/wmem_strutl.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/epan/wmem/wmem_strbuf.c b/epan/wmem/wmem_strbuf.c index bd074e7584..0a0f1a5f56 100644 --- a/epan/wmem/wmem_strbuf.c +++ b/epan/wmem/wmem_strbuf.c @@ -29,6 +29,10 @@ #include "wmem_core.h" #include "wmem_strbuf.h" +#ifdef _WIN32 +#include +#endif + #define DEFAULT_MINIMUM_LEN 16 /* Holds a wmem-allocated string-buffer. @@ -154,6 +158,7 @@ wmem_strbuf_append(wmem_strbuf_t *strbuf, const gchar *str) strbuf->len = MIN(strbuf->len + append_len, strbuf->alloc_len - 1); } +#ifndef _WIN32 static void wmem_strbuf_append_vprintf(wmem_strbuf_t *strbuf, const gchar *fmt, va_list ap) { @@ -176,6 +181,37 @@ wmem_strbuf_append_vprintf(wmem_strbuf_t *strbuf, const gchar *fmt, va_list ap) strbuf->len = MIN(strbuf->len + append_len, strbuf->alloc_len - 1); } +#else /* _WIN32 */ +/* + * GLib's v*printf routines are surprisingly slow on Windows, at least with + * GLib 2.40.0. This appears to be due to GLib using the gnulib version of + * vasnprintf when compiled under MinGW. If GLib ever ends up using the + * native Windows v*printf routines this can be removed. + */ +static void +wmem_strbuf_append_vprintf(wmem_strbuf_t *strbuf, const gchar *fmt, va_list ap) +{ + va_list ap2; + gsize append_len; + gsize printed_len; + + G_VA_COPY(ap2, ap); + + append_len = _vscprintf(fmt, ap); + + wmem_strbuf_grow(strbuf, append_len); + + printed_len = vsnprintf_s(&strbuf->str[strbuf->len], + (gulong) WMEM_STRBUF_RAW_ROOM(strbuf), + _TRUNCATE, + fmt, ap2); + if (printed_len > -1) append_len = printed_len; + + va_end(ap2); + + strbuf->len = MIN(strbuf->len + append_len, strbuf->alloc_len - 1); +} +#endif /* _WIN32 */ void wmem_strbuf_append_printf(wmem_strbuf_t *strbuf, const gchar *format, ...) diff --git a/epan/wmem/wmem_strutl.c b/epan/wmem/wmem_strutl.c index c35f2e68f0..009abf1d80 100644 --- a/epan/wmem/wmem_strutl.c +++ b/epan/wmem/wmem_strutl.c @@ -26,6 +26,10 @@ #include #include +#ifdef _WIN32 +#include +#endif + #include #include "wmem_core.h" @@ -86,6 +90,7 @@ wmem_strdup_printf(wmem_allocator_t *allocator, const gchar *fmt, ...) * in my test file all strings was less than 72 characters long and quite a few * over 68 characters long. Chose 80 as the default. */ +#ifndef _WIN32 #define WMEM_STRDUP_VPRINTF_DEFAULT_BUFFER 80 gchar * wmem_strdup_vprintf(wmem_allocator_t *allocator, const gchar *fmt, va_list ap) @@ -115,6 +120,33 @@ wmem_strdup_vprintf(wmem_allocator_t *allocator, const gchar *fmt, va_list ap) return dst; } +#else /* _WIN32 */ +/* + * GLib's v*printf routines are surprisingly slow on Windows, at least with + * GLib 2.40.0. This appears to be due to GLib using the gnulib version of + * vasnprintf when compiled under MinGW. If GLib ever ends up using the + * native Windows v*printf routines this can be removed. + */ +gchar * +wmem_strdup_vprintf(wmem_allocator_t *allocator, const gchar *fmt, va_list ap) +{ + va_list ap2; + gchar *dst; + int needed_len; + + G_VA_COPY(ap2, ap); + + needed_len = _vscprintf(fmt, ap2) + 1; + + dst = (gchar *)wmem_alloc(allocator, needed_len); + + vsprintf(dst, fmt, ap2); + + va_end(ap2); + + return dst; +} +#endif /* _WIN32 */ gchar * wmem_strconcat(wmem_allocator_t *allocator, const gchar *first, ...)