From a46944a59963a78821c0300fc24a7d813087b3b7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 8 Aug 2025 22:56:47 +0200 Subject: [PATCH] tool_cb_wrt: stop alloc/free for every chunk windows console output Instead realloc to the largest buffer and keep that for reuse during the entire lifetime. Co-authored-by: Jay Satiro Closes #18233 --- src/tool_cb_wrt.c | 36 +++++++++++++++++++----------------- src/tool_cfgable.c | 3 +++ src/tool_cfgable.h | 10 ++++++++++ 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c index ff544e61a2..6fbf80753d 100644 --- a/src/tool_cb_wrt.c +++ b/src/tool_cb_wrt.c @@ -115,8 +115,7 @@ static size_t win_console(intptr_t fhnd, struct OutStruct *outs, char *buffer, size_t bytes, size_t *retp) { - wchar_t *wc_buf; - DWORD wc_len, chars_written; + DWORD chars_written; unsigned char *rbuf = (unsigned char *)buffer; DWORD rlen = (DWORD)bytes; @@ -206,27 +205,30 @@ static size_t win_console(intptr_t fhnd, struct OutStruct *outs, if(rlen) { /* calculate buffer size for wide characters */ - wc_len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen, - NULL, 0); - if(!wc_len) + DWORD len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, + (int)rlen, NULL, 0); + if(!len) return CURL_WRITEFUNC_ERROR; - wc_buf = (wchar_t*) malloc(wc_len * sizeof(wchar_t)); - if(!wc_buf) - return CURL_WRITEFUNC_ERROR; + /* grow the buffer if needed */ + if(len > global->term.len) { + wchar_t *buf = (wchar_t *) realloc(global->term.buf, + len * sizeof(wchar_t)); + if(!buf) + return CURL_WRITEFUNC_ERROR; + global->term.len = len; + global->term.buf = buf; + } - wc_len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen, - wc_buf, (int)wc_len); - if(!wc_len) { - free(wc_buf); + len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen, + global->term.buf, + (int)len); + if(!len) return CURL_WRITEFUNC_ERROR; - } - if(!WriteConsoleW((HANDLE) fhnd, wc_buf, wc_len, &chars_written, NULL)) { - free(wc_buf); + if(!WriteConsoleW((HANDLE) fhnd, global->term.buf, + len, &chars_written, NULL)) return CURL_WRITEFUNC_ERROR; - } - free(wc_buf); } *retp = bytes; diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c index 015ee26cbe..0321848b0d 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c @@ -263,6 +263,9 @@ static void free_globalconfig(void) global->trace_stream = NULL; tool_safefree(global->libcurl); +#if defined(_WIN32) && !defined(UNDER_CE) + free(global->term.buf); +#endif } /* diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index f982d22d62..23e874f448 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -339,6 +339,13 @@ struct OperationConfig { BIT(skip_existing); }; +#if defined(_WIN32) && !defined(UNDER_CE) +struct termout { + wchar_t *buf; + DWORD len; +}; +#endif + struct GlobalConfig { struct State state; /* for create_transfer() */ char *trace_dump; /* file to dump the network trace to */ @@ -351,6 +358,9 @@ struct GlobalConfig { struct OperationConfig *first; struct OperationConfig *current; struct OperationConfig *last; +#if defined(_WIN32) && !defined(UNDER_CE) + struct termout term; +#endif timediff_t ms_per_transfer; /* start next transfer after (at least) this many milliseconds */ trace tracetype; -- 2.47.3