bin/87792: very bad performance of cp(1) via NFS,
possibly mmap() problem
Andre Albsmeier
Andre.Albsmeier at siemens.com
Fri Oct 21 09:40:17 PDT 2005
>Number: 87792
>Category: bin
>Synopsis: very bad performance of cp(1) via NFS, possibly mmap() problem
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri Oct 21 16:40:15 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Andre Albsmeier
>Release: FreeBSD 5.4-STABLE i386
>Organization:
>Environment:
Two machines, a local one which copies files to a remote
machine via NFS using cp. Both machines use FreeBSD 5.4-STABLE.
>Description:
cp uses mmap() to copy files < 8MB. When files are copied
from the local host to a remote box via NFS data is transferred
very slowly. For bigger files, cp uses read() and write()
alternately which performs very well.
>How-To-Repeat:
I have two files, one is 6MB in size and the other one is 12MB.
I copy them from the local box to an NFS mounted directory named
/scratch:
andre at bali:/tmp>time cp 12mb /scratch
cp 12mb /scratch 0.00s user 0.12s system 10% cpu 1.142 total
andre at bali:/tmp>time cp 6mb /scratch
cp 6mb /scratch 0.00s user 0.13s system 0% cpu 14.274 total
The 12MB filecopy performs quite well as I would expect it
from a 100MBit network. The 6mb filecopy I won't comment on :-).
(This is an extreme case, other client-server combinations
are faster. The "fastest" one I found was 4 seconds which is
still bad for a 6MB file).
In the mmap() case, the whole source file is mmap'ed and
one write() call is used which tries to write the whole file
all at once. I have modified copy_file() in utils.c in a way
that instead of one "big" write(), several small ones are
being made (this is no fix, just for demonstration):
--- utils.c.ORI Thu Aug 19 07:04:27 2004
+++ utils.c Fri Oct 21 18:19:59 2005
@@ -140,7 +140,11 @@
wtotal = 0;
for (bufp = p, wresid = fs->st_size; ;
bufp += wcount, wresid -= (size_t)wcount) {
+#if 0
wcount = write(to_fd, bufp, wresid);
+#else
+ wcount = write(to_fd, bufp, wresid > 65536 ? 65536 : wresid );
+#endif
wtotal += wcount;
if (info) {
info = 0;
65536 is just a value for playing; almost everything below
1M and not ridiculous small will do it:
andre at bali:/tmp>time cp 6mb /scratch
cp 6mb /scratch 0.00s user 0.05s system 8% cpu 0.618 total
>Fix:
I have no idea. FreeBSD-4 uses the same mmap() thingy in utils.c
and here performance is ok so I assume the problem is somewhere
else than in the cp sources.
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list