* src/cat.c (main): Only resize the allocated buffer when needed,
which avoids per file heap manipulation and mmap/munmap syscalls.
---
src/cat.c | 50 ++++++++++++++++++++++++++++++++------------------
1 file changed, 32 insertions(+), 18 deletions(-)
diff --git a/src/cat.c b/src/cat.c
index 28dd55ea3..01a703e9b 100644
--- a/src/cat.c
+++ b/src/cat.c
@@ -643,6 +643,21 @@ splice_cat (void)
return (in_ok && out_ok) ? some_copied : -1;
}
+/* Reuse an aligned buffer across inputs, growing it only as needed. */
+
+static char *
+ensure_buf_size (char *buf, idx_t *buf_alloc, idx_t alignment, idx_t size)
+{
+ if (*buf_alloc < size)
+ {
+ alignfree (buf);
+ buf = xalignalloc (alignment, size);
+ *buf_alloc = size;
+ }
+
+ return buf;
+}
+
int
main (int argc, char **argv)
{
@@ -774,6 +789,10 @@ main (int argc, char **argv)
int argind = optind;
bool ok = true;
idx_t page_size = getpagesize ();
+ char *inbuf = NULL;
+ char *outbuf = NULL;
+ idx_t inbuf_alloc = 0;
+ idx_t outbuf_alloc = 0;
do
{
@@ -838,9 +857,6 @@ main (int argc, char **argv)
}
}
- /* Pointer to the input buffer. */
- char *inbuf;
-
/* Select which version of 'cat' to use. If any format-oriented
options were given use 'cat'; if not, use 'copy_cat' if it
works, 'simple_cat' otherwise. */
@@ -851,10 +867,7 @@ main (int argc, char **argv)
int copy_cat_status =
out_isreg && S_ISREG (istat_buf.st_mode) ? copy_cat () : 0;
if (copy_cat_status != 0)
- {
- inbuf = NULL;
- ok &= 0 < copy_cat_status;
- }
+ ok &= 0 < copy_cat_status;
else
{
/* Note 32768 was determined as the limit when splice
@@ -865,14 +878,12 @@ main (int argc, char **argv)
&& istat_buf.st_size <= 32768)
? 0 : splice_cat ());
if (splice_cat_status != 0)
- {
- inbuf = NULL;
- ok &= 0 < splice_cat_status;
- }
+ ok &= 0 < splice_cat_status;
else
{
insize = MAX (insize, outsize);
- inbuf = xalignalloc (page_size, insize);
+ inbuf = ensure_buf_size (inbuf, &inbuf_alloc,
+ page_size, insize);
ok &= simple_cat (inbuf, insize);
}
}
@@ -880,7 +891,8 @@ main (int argc, char **argv)
else
{
/* Allocate, with an extra byte for a newline sentinel. */
- inbuf = xalignalloc (page_size, insize + 1);
+ inbuf = ensure_buf_size (inbuf, &inbuf_alloc,
+ page_size, insize + 1);
/* Why are
(OUTSIZE - 1 + INSIZE * 4 + LINE_COUNTER_BUF_LEN)
@@ -908,17 +920,14 @@ main (int argc, char **argv)
|| ckd_add (&bufsize, bufsize, outsize)
|| ckd_add (&bufsize, bufsize, LINE_COUNTER_BUF_LEN - 1))
xalloc_die ();
- char *outbuf = xalignalloc (page_size, bufsize);
+ outbuf = ensure_buf_size (outbuf, &outbuf_alloc,
+ page_size, bufsize);
ok &= cat (inbuf, insize, outbuf, outsize, show_nonprinting,
show_tabs, number, number_nonblank, show_ends,
squeeze_blank);
-
- alignfree (outbuf);
}
- alignfree (inbuf);
-
contin:
if (!reading_stdin && close (input_desc) < 0)
{
@@ -934,6 +943,11 @@ main (int argc, char **argv)
write_error ();
}
+#ifdef lint
+ alignfree (outbuf);
+ alignfree (inbuf);
+#endif
+
if (have_read_stdin && close (STDIN_FILENO) < 0)
error (EXIT_FAILURE, errno, _("closing standard input"));
--
2.53.0