* Instrument tcp_build_datapkt().

* Remove the code that allocates a cluster if the packet would
  fit in one; it totally defeats doing references to M_EXT mbufs
  in the socket buffer.  This drastically reduces the number of
  data copies in the tcp_output() path for applications which use
  large writes.  Kudos to Matt Thomas for pointing me in the right
  direction.
This commit is contained in:
thorpej 2002-04-27 01:47:58 +00:00
parent 76d2795556
commit 9054daca3e
2 changed files with 59 additions and 10 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_output.c,v 1.78 2002/03/01 22:54:09 thorpej Exp $ */
/* $NetBSD: tcp_output.c,v 1.79 2002/04/27 01:47:58 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -142,7 +142,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.78 2002/03/01 22:54:09 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.79 2002/04/27 01:47:58 thorpej Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -200,6 +200,21 @@ extern struct mbuf *m_copypack();
int tcp_cwm = 1;
int tcp_cwm_burstsize = 4;
#ifdef TCP_OUTPUT_COUNTERS
#include <sys/device.h>
extern struct evcnt tcp_output_bigheader;
extern struct evcnt tcp_output_copysmall;
extern struct evcnt tcp_output_copybig;
extern struct evcnt tcp_output_refbig;
#define TCP_OUTPUT_COUNTER_INCR(ev) (ev)->ev_count++
#else
#define TCP_OUTPUT_COUNTER_INCR(ev) /* nothing */
#endif /* TCP_OUTPUT_COUNTERS */
static
#ifndef GPROF
__inline
@ -384,29 +399,43 @@ tcp_build_datapkt(struct tcpcb *tp, struct socket *so, int off,
m->m_data -= hdrlen;
#else
MGETHDR(m, M_DONTWAIT, MT_HEADER);
if (m != NULL &&
(max_linkhdr + hdrlen > MHLEN ||
max_linkhdr + hdrlen + len <= MCLBYTES)) {
if (__predict_false(m == NULL))
return (ENOBUFS);
/*
* XXX Because other code assumes headers will fit in
* XXX one header mbuf.
*
* (This code should almost *never* be run.)
*/
if (__predict_false((max_linkhdr + hdrlen) > MHLEN)) {
TCP_OUTPUT_COUNTER_INCR(&tcp_output_bigheader);
MCLGET(m, M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
m_freem(m);
m = NULL;
return (ENOBUFS);
}
}
if (m == NULL)
return (ENOBUFS);
m->m_data += max_linkhdr;
m->m_len = hdrlen;
if (len <= M_TRAILINGSPACE(m)) {
m_copydata(so->so_snd.sb_mb, off, (int) len,
mtod(m, caddr_t) + hdrlen);
m->m_len += len;
TCP_OUTPUT_COUNTER_INCR(&tcp_output_copysmall);
} else {
m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
if (m->m_next == NULL) {
m_freem(m);
return (ENOBUFS);
}
#ifdef TCP_OUTPUT_COUNTERS
if (m->m_next->m_flags & M_EXT)
TCP_OUTPUT_COUNTER_INCR(&tcp_output_refbig);
else
TCP_OUTPUT_COUNTER_INCR(&tcp_output_copybig);
#endif /* TCP_OUTPUT_COUNTERS */
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_subr.c,v 1.124 2002/03/15 09:25:41 itojun Exp $ */
/* $NetBSD: tcp_subr.c,v 1.125 2002/04/27 01:47:58 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -102,7 +102,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.124 2002/03/15 09:25:41 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.125 2002/04/27 01:47:58 thorpej Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -227,6 +227,19 @@ struct evcnt tcp_swcsum = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
NULL, "tcp", "swcsum");
#endif /* TCP_CSUM_COUNTERS */
#ifdef TCP_OUTPUT_COUNTERS
#include <sys/device.h>
struct evcnt tcp_output_bigheader = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
NULL, "tcp", "output big header");
struct evcnt tcp_output_copysmall = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
NULL, "tcp", "output copy small");
struct evcnt tcp_output_copybig = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
NULL, "tcp", "output copy big");
struct evcnt tcp_output_refbig = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
NULL, "tcp", "output reference big");
#endif /* TCP_OUTPUT_COUNTERS */
/*
* Tcp initialization
*/
@ -271,6 +284,13 @@ tcp_init()
evcnt_attach_static(&tcp_hwcsum_data);
evcnt_attach_static(&tcp_swcsum);
#endif /* TCP_CSUM_COUNTERS */
#ifdef TCP_OUTPUT_COUNTERS
evcnt_attach_static(&tcp_output_bigheader);
evcnt_attach_static(&tcp_output_copysmall);
evcnt_attach_static(&tcp_output_copybig);
evcnt_attach_static(&tcp_output_refbig);
#endif /* TCP_OUTPUT_COUNTERS */
}
/*