From 327caad7a1aa5b506b20fd6a1d086be2bb031eea Mon Sep 17 00:00:00 2001 From: millert Date: Sun, 28 Apr 2024 14:28:02 +0000 Subject: [PATCH] __sfvwrite: allow writing buffers larger than BUFSIZ or st_blksize. This can vastly improve write performance. For unbuffered writes, we now write up to INT_MAX instead of BUFSIZE. For buffered writes, write the largest multiple of the buffer size (which may be st_blksize). From Apple via enh at google. OK tb@ --- lib/libc/stdio/fvwrite.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/libc/stdio/fvwrite.c b/lib/libc/stdio/fvwrite.c index d83de884581..d615245abc2 100644 --- a/lib/libc/stdio/fvwrite.c +++ b/lib/libc/stdio/fvwrite.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fvwrite.c,v 1.21 2023/10/06 16:41:02 millert Exp $ */ +/* $OpenBSD: fvwrite.c,v 1.22 2024/04/28 14:28:02 millert Exp $ */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. @@ -31,6 +31,7 @@ * SUCH DAMAGE. */ +#include #include #include #include @@ -76,11 +77,12 @@ __sfvwrite(FILE *fp, struct __suio *uio) } if (fp->_flags & __SNBF) { /* - * Unbuffered: write up to BUFSIZ bytes at a time. + * Unbuffered: write up to INT_MAX bytes at a time, to not + * truncate the value of len if it is greater than 2^31 bytes. */ do { GETIOV(;); - w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ)); + w = (*fp->_write)(fp->_cookie, p, MIN(len, INT_MAX)); if (w <= 0) goto err; p += w; @@ -90,7 +92,8 @@ __sfvwrite(FILE *fp, struct __suio *uio) /* * Fully buffered: fill partially full buffer, if any, * and then flush. If there is no partial buffer, write - * one _bf._size byte chunk directly (without copying). + * entire payload directly (without copying) up to a + * multiple of the buffer size. * * String output is a special case: write as many bytes * as fit, but pretend we wrote everything. This makes @@ -134,7 +137,15 @@ __sfvwrite(FILE *fp, struct __suio *uio) if (__sflush(fp)) goto err; } else if (len >= (w = fp->_bf._size)) { - /* write directly */ + /* + * Write directly up to INT_MAX or greatest + * multiple of buffer size (whichever is + * smaller), keeping in the memory buffer the + * remaining part of payload that is smaller + * than buffer size. + */ + if (w != 0) + w = MIN(w * (len / w), INT_MAX); w = (*fp->_write)(fp->_cookie, p, w); if (w <= 0) goto err; -- 2.20.1