]> xenbits.xensource.com Git - people/royger/freebsd.git/commitdiff
fread: improve performance for unbuffered reads
authorPedro F. Giffuni <pfg@FreeBSD.org>
Mon, 31 May 2021 01:48:38 +0000 (20:48 -0500)
committerPedro F. Giffuni <pfg@FreeBSD.org>
Tue, 1 Jun 2021 21:00:28 +0000 (16:00 -0500)
We can use the buffer passed to fread(3) directly in the FILE *.
The buffer needs to be reset before each call to __srefill().
This preserves the expected behavior in all cases.

The change was found originally in OpenBSD and later adopted by NetBSD.

MFC after: 2 weeks
Obtained from: OpenBSD (CVS 1.18)

Differential Revision: https://reviews.freebsd.org/D30548

lib/libc/stdio/fread.c

index c12bcf1148b7569660dba94717d17b4b7dfd75c4..11f8d13f0caf6db6b8deb54732cf661a1c72d390 100644 (file)
@@ -99,6 +99,35 @@ __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
                fp->_r = 0;
        total = resid;
        p = buf;
+
+       /*
+        * If we're unbuffered we know that the buffer in fp is empty so
+        * we can read directly into buf.  This is much faster than a
+        * series of one byte reads into fp->_nbuf.
+        */
+       if ((fp->_flags & __SNBF) != 0 && buf != NULL) {
+               while (resid > 0) {
+                       /* set up the buffer */
+                       fp->_bf._base = fp->_p = p;
+                       fp->_bf._size = resid;
+
+                       if (__srefill(fp)) {
+                               /* no more input: return partial result */
+                               count = (total - resid) / size;
+                               break;
+                       }
+                       p += fp->_r;
+                       resid -= fp->_r;
+               }
+
+               /* restore the old buffer (see __smakebuf) */
+               fp->_bf._base = fp->_p = fp->_nbuf;
+               fp->_bf._size = 1;
+               fp->_r = 0;
+
+               return (count);
+       }
+
        while (resid > (r = fp->_r)) {
                (void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
                fp->_p += r;