summaryrefslogtreecommitdiffstats
path: root/bin/cat
diff options
context:
space:
mode:
authorivoras <ivoras@FreeBSD.org>2008-10-30 14:05:57 +0000
committerivoras <ivoras@FreeBSD.org>2008-10-30 14:05:57 +0000
commit1f332d86bf5e4cfc63df682d8859c4f4fac21026 (patch)
tree346118ee48560d0625d63c6017022305731d9dd9 /bin/cat
parentfbca48f8d5b2e879565c548e81b7c3da7d1b36dc (diff)
downloadFreeBSD-src-1f332d86bf5e4cfc63df682d8859c4f4fac21026.zip
FreeBSD-src-1f332d86bf5e4cfc63df682d8859c4f4fac21026.tar.gz
Teach cat(1) and cp(1) to use a larger buffer if enough memory is present
in the system. A simple heuristics is used to detect what is "enough" memory: if number of physmem pages is greater than 32k (equalling 128 MB on machines with 4 kB pages). Typical immediate result of these changes is reduction in context switches and the goal is to increase efficiency by using large buffers: before: /usr/bin/time -hlp cat file1 > file2 ... 163 voluntary context switches 11194 involuntary context switches after: /usr/bin/time -hlp ./cat file1 > file2 ... 417 voluntary context switches 272 involuntary context switches Reviewed by: hackers@ (no objections to earlier version of cat patch) Approved by: gnn (mentor) MFC after: 4 months
Diffstat (limited to 'bin/cat')
-rw-r--r--bin/cat/cat.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/bin/cat/cat.c b/bin/cat/cat.c
index 9acd68f..d338742 100644
--- a/bin/cat/cat.c
+++ b/bin/cat/cat.c
@@ -77,6 +77,17 @@ static void raw_cat(int);
static int udom_open(const char *path, int flags);
#endif
+/* Memory strategy threshold, in pages: if physmem is larger then this, use a
+ * large buffer */
+#define PHYSPAGES_THRESHOLD (32*1024)
+
+/* Maximum buffer size in bytes - do not allow it to grow larger than this */
+#define BUFSIZE_MAX (2*1024*1024)
+
+/* Small (default) buffer size in bytes. It's inefficient for this to be
+ * smaller than MAXPHYS */
+#define BUFSIZE_SMALL (MAXPHYS)
+
int
main(int argc, char *argv[])
{
@@ -247,9 +258,17 @@ raw_cat(int rfd)
if (buf == NULL) {
if (fstat(wfd, &sbuf))
err(1, "%s", filename);
- bsize = MAX(sbuf.st_blksize, 1024);
+ if (S_ISREG(sbuf.st_mode)) {
+ /* If there's plenty of RAM, use a large copy buffer */
+ if (sysconf(_SC_PHYS_PAGES) > PHYSPAGES_THRESHOLD)
+ bsize = MIN(BUFSIZE_MAX, MAXPHYS*8);
+ else
+ bsize = BUFSIZE_SMALL;
+ } else
+ bsize = MAX(sbuf.st_blksize,
+ (blksize_t)sysconf(_SC_PAGESIZE));
if ((buf = malloc(bsize)) == NULL)
- err(1, "buffer");
+ err(1, "malloc() failure of IO buffer");
}
while ((nr = read(rfd, buf, bsize)) > 0)
for (off = 0; nr; nr -= nw, off += nw)
OpenPOWER on IntegriCloud