]> git.eshelyaron.com Git - emacs.git/commitdiff
Avoid some tiny /proc file reads
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 13 Jul 2025 19:52:43 +0000 (12:52 -0700)
committerEshel Yaron <me@eshelyaron.com>
Thu, 24 Jul 2025 08:49:06 +0000 (10:49 +0200)
* src/fileio.c (union read_non_regular):
New members buf and bufsize replace inserted and trytry.
(read_non_regular): Adjust to this new, simpler interface.
(Finsert_file_contents): If the gap is smaller than read_buf
and we want to read more than the gap, read into read_buf
first, to avoid lots of tiny reads from /proc files.

(cherry picked from commit c3f96d20eecdf0aa93f294a4f3fb96e16eec6a68)

src/fileio.c

index 2a53dbbdd07524e16b7432cc390c42dcdebe2437..075b9c590c8fbb03fa6bc6ec2faf1f9c384f731e 100644 (file)
@@ -3906,7 +3906,8 @@ union read_non_regular
   struct
   {
     emacs_fd fd;
-    ptrdiff_t inserted, trytry;
+    char *buf;
+    ptrdiff_t bufsize;
   } s;
   GCALIGNED_UNION_MEMBER
 };
@@ -3916,11 +3917,7 @@ static Lisp_Object
 read_non_regular (Lisp_Object state)
 {
   union read_non_regular *data = XFIXNUMPTR (state);
-  intmax_t nbytes
-    = emacs_fd_read (data->s.fd,
-                    ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE
-                     + data->s.inserted),
-                    data->s.trytry);
+  intmax_t nbytes = emacs_fd_read (data->s.fd, data->s.buf, data->s.bufsize);
   return make_int (nbytes < 0 ? -errno : nbytes);
 }
 
@@ -4854,18 +4851,18 @@ by calling `format-decode', which see.  */)
 
     while (inserted < total)
       {
-       ptrdiff_t this;
-
-       if (gap_size == 0)
+       char *buf;
+       ptrdiff_t bufsize, this;
+       if (gap_size < total - inserted && gap_size < sizeof read_buf)
          {
-           /* The size estimate was wrong.  Make the gap 50% larger.  */
-           make_gap (GAP_SIZE >> 1);
-           gap_size = GAP_SIZE - inserted;
+           buf = read_buf;
+           bufsize = sizeof read_buf;
+         }
+       else
+         {
+           buf = (char *) BEG_ADDR + PT_BYTE - BEG_BYTE + inserted;
+           bufsize = min (min (gap_size, total - inserted), READ_BUF_SIZE);
          }
-
-       /* 'try' is reserved in some compilers (Microsoft C).  */
-       ptrdiff_t trytry = min (gap_size,
-                               min (total - inserted, READ_BUF_SIZE));
 
        if (!seekable && end_offset == TYPE_MAXIMUM (off_t))
          {
@@ -4875,7 +4872,7 @@ by calling `format-decode', which see.  */)
            /* Read from the file, capturing `quit'.  When an
               error occurs, end the loop, and arrange for a quit
               to be signaled after decoding the text we read.  */
-           union read_non_regular data = {{fd, inserted, trytry}};
+           union read_non_regular data = {{fd, buf, bufsize}};
            nbytes = internal_condition_case_1
              (read_non_regular, make_pointer_integer (&data),
               Qerror, read_non_regular_quit);
@@ -4894,11 +4891,7 @@ by calling `format-decode', which see.  */)
             part of the buffer until all the reading is done, so a
             C-g here doesn't do any harm.  */
          {
-           this = emacs_fd_read (fd,
-                                 ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE
-                                  + inserted),
-                                 trytry);
-           if (this < 0)
+           this = emacs_fd_read (fd, buf, bufsize);                                        if (this < 0)
              this = -errno;
          }
 
@@ -4908,6 +4901,20 @@ by calling `format-decode', which see.  */)
            break;
          }
 
+       if (buf == read_buf)
+         {
+           if (gap_size < this)
+             {
+               /* Size estimate was low.  Make the gap at least 50% larger,
+                  and big enough so that the next loop iteration will
+                  use the gap directly instead of copying via read_buf.  */
+               make_gap (max (GAP_SIZE >> 1,
+                              this - gap_size + sizeof read_buf));
+               gap_size = GAP_SIZE - inserted;
+             }
+           memcpy (BEG_ADDR + PT_BYTE - BEG_BYTE + inserted,
+                   read_buf, this);
+         }
        gap_size -= this;
        inserted += this;
       }