diff options
author | glebius <glebius@FreeBSD.org> | 2012-06-04 12:49:21 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2012-06-04 12:49:21 +0000 |
commit | df2b290f0d9df8886ee3832df87616c18dbf2abb (patch) | |
tree | 1b6b4e6f0ba12585743bd02d4a6ef5187f212ed0 | |
parent | 511c0436a1ec049b8f3992edbb3bb4c2cd0fdddc (diff) | |
download | FreeBSD-src-df2b290f0d9df8886ee3832df87616c18dbf2abb.zip FreeBSD-src-df2b290f0d9df8886ee3832df87616c18dbf2abb.tar.gz |
Optimise kern_sendfile(): skip cycling through the entire mbuf chain in
m_cat(), storing pointer to last mbuf in chain in local variable and
attaching new mbuf to the end of chain.
Submitter reports that CPU load dropped for > 10% on a web server
serving large files with this optimisation.
Submitted by: Sergey Budnevitch <sb nginx.com>
-rw-r--r-- | sys/kern/uipc_syscalls.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 4502e43..16933fe 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1962,6 +1962,7 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap, * and takes care of the overall progress. */ for (off = uap->offset, rem = uap->nbytes; ; ) { + struct mbuf *mtail = NULL; int loopbytes = 0; int space = 0; int done = 0; @@ -2181,10 +2182,15 @@ retry_space: m0->m_len = xfsize; /* Append to mbuf chain. */ - if (m != NULL) - m_cat(m, m0); - else - m = m0; + if (mtail != NULL) { + mtail->m_next = m0; + } else { + if (m != NULL) + m_cat(m, m0); + else + m = m0; + } + mtail = m0; /* Keep track of bits processed. */ loopbytes += xfsize; |