diff options
author | ivoras <ivoras@FreeBSD.org> | 2008-10-30 14:05:57 +0000 |
---|---|---|
committer | ivoras <ivoras@FreeBSD.org> | 2008-10-30 14:05:57 +0000 |
commit | 1f332d86bf5e4cfc63df682d8859c4f4fac21026 (patch) | |
tree | 346118ee48560d0625d63c6017022305731d9dd9 /bin/cat | |
parent | fbca48f8d5b2e879565c548e81b7c3da7d1b36dc (diff) | |
download | FreeBSD-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.c | 23 |
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) |