From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mta1.formilux.org (mta1.formilux.org [51.159.59.229]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E7F6C2DE6EF for ; Sat, 7 Feb 2026 19:29:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=51.159.59.229 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770492577; cv=none; b=lVhlsx3a+cfgQBADtc6KZW3gt8Pp0+O/3GDcJ20Vm/38c4seilhasx8/Pbo20ynLIIinv8xEZDy4j8KaEd0Dl3T9vf7cLnFk/ZwegMEK852jxm0U/HQqL6/GUxwlp1t414hlqzZSQ4uhk+r3tmWu6UwDLWJZarUrqa1uCCIz7+I= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770492577; c=relaxed/simple; bh=8vP3SwHuucTXSazhhP2ENOI3G6GVEtLvaD+JqJtt5nQ=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=CUnkPW08gaoLbTi/gHOcRRDMVCtOJBWUOh/N6KLd8Q4uTEBLP1wKxIib96cdFXeg753821e9S/8lC9VCDq281N9Flw5O4jnoHHRNoXos78kDUGpDZliCjRcwpvyiaXu4XxnRsv/RhP4oWtACD0fQjY9pLQFx+EH+9uWONhV/RPE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=1wt.eu; spf=pass smtp.mailfrom=1wt.eu; dkim=pass (1024-bit key) header.d=1wt.eu header.i=@1wt.eu header.b=EvPz5eH9; arc=none smtp.client-ip=51.159.59.229 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=1wt.eu Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=1wt.eu Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=1wt.eu header.i=@1wt.eu header.b="EvPz5eH9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1wt.eu; s=mail; t=1770492575; bh=vkwG64aofMr4r6JTAUNmc45Z6q4vrwa6uPNIOjstMkk=; h=From:Message-ID:From; b=EvPz5eH9q1Sxa9a3j+w0cqk8r2ctc4NfR4EyOMbE0w4pF7Rfb3z20Ru9DkTorGT3I ls65OG8ij77B3kyu0O56sV0HNDa02dHWfrPhKa6LyM5YdHuJTPU4pyMcPJYBMAuFzv i0bl67SCMGFSW4zaj4Lk9yOVSHredEkp644azB/A= Received: from 1wt.eu (ded1.1wt.eu [163.172.96.212]) by mta1.formilux.org (Postfix) with ESMTP id 12046C0B45; Sat, 07 Feb 2026 20:29:35 +0100 (CET) Date: Sat, 7 Feb 2026 20:29:34 +0100 From: Willy Tarreau To: david.laight.linux@gmail.com Cc: Thomas =?iso-8859-1?Q?Wei=DFschuh?= , linux-kernel@vger.kernel.org, Cheng Li Subject: Re: [PATCH v2 next 03/11] tools/nolibc/printf: Add buffering to vfprintf() callback. Message-ID: References: <20260206191121.3602-1-david.laight.linux@gmail.com> <20260206191121.3602-4-david.laight.linux@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20260206191121.3602-4-david.laight.linux@gmail.com> On Fri, Feb 06, 2026 at 07:11:13PM +0000, david.laight.linux@gmail.com wrote: > From: David Laight > > Add per-call buffering to the vprintf() callback. > While this adds some extra code it will speed things up and > makes a massive difference to anyone looking at strace output. This patch alone adds more than 200 extra bytes to the smallest binary for something that was never expressed as a need by users: $ size hello-patch* text data bss dec hex filename 1859 48 24 1931 78b hello-patch1 2071 48 24 2143 85f hello-patch2 I doubt it would make sense to have a build option to choose this. Or alternately one could decide do disable it when __OPTIMIZE_SIZE__ is defined. I just tried quickly and it does the job: @@ -390,6 +390,7 @@ struct __nolibc_fprintf_cb_state { static int __nolibc_fprintf_cb(void *v_state, const char *buf, size_t size) { +#if !defined(__OPTIMIZE_SIZE__) struct __nolibc_fprintf_cb_state *state = v_state; unsigned int off = state->buf_offset; @@ -407,16 +408,24 @@ static int __nolibc_fprintf_cb(void *v_state, const char *buf, size_t size) memcpy(state->buf + off, buf, size); } return 0; +#else + /* v_state is the stream */ + return size ? _fwrite(buf, size, v_state) : 0; +#endif } static __attribute__((unused, format(printf, 2, 0))) int vfprintf(FILE *stream, const char *fmt, va_list args) { +#if !defined(__OPTIMIZE_SIZE__) struct __nolibc_fprintf_cb_state state; state.stream = stream; state.buf_offset = 0; return __nolibc_printf(__nolibc_fprintf_cb, &state, fmt, args); +#else + return __nolibc_printf(__nolibc_fprintf_cb, stream, fmt, args); +#endif } static __attribute__((unused, format(printf, 1, 0))) > Signed-off-by: David Laight > --- > > Changes for v2: > Formally patch 2, unchanged. > > tools/include/nolibc/stdio.h | 32 +++++++++++++++++++++++++++++--- > 1 file changed, 29 insertions(+), 3 deletions(-) > > diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h > index 36733ecd4261..552f09d51d82 100644 > --- a/tools/include/nolibc/stdio.h > +++ b/tools/include/nolibc/stdio.h > @@ -382,15 +382,41 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *state, const char *fmt, va_list > return written; > } > > -static int __nolibc_fprintf_cb(void *stream, const char *buf, size_t size) > +struct __nolibc_fprintf_cb_state { > + FILE *stream; > + unsigned int buf_offset; > + char buf[128]; > +}; So that's the other state I was wondering if we could merge with the first one. > +static int __nolibc_fprintf_cb(void *v_state, const char *buf, size_t size) > { > - return size ? _fwrite(buf, size, stream) : 0; > + struct __nolibc_fprintf_cb_state *state = v_state; > + unsigned int off = state->buf_offset; > + > + if (off + size > sizeof(state->buf) || buf == NULL) { Please mention that special case of buf==NULL in a comment above the function. That's an internal API choice. > + state->buf_offset = 0; > + if (off && _fwrite(state->buf, off, state->stream)) > + return -1; > + if (size > sizeof(state->buf)) > + return _fwrite(buf, size, state->stream); > + off = 0; > + } > + > + if (size) { > + state->buf_offset = off + size; > + memcpy(state->buf + off, buf, size); > + } > + return 0; > } > > static __attribute__((unused, format(printf, 2, 0))) > int vfprintf(FILE *stream, const char *fmt, va_list args) > { > - return __nolibc_printf(__nolibc_fprintf_cb, stream, fmt, args); > + struct __nolibc_fprintf_cb_state state; > + > + state.stream = stream; > + state.buf_offset = 0; > + return __nolibc_printf(__nolibc_fprintf_cb, &state, fmt, args); > } > > static __attribute__((unused, format(printf, 1, 0))) Thanks, Willy