mirror of
https://github.com/openbsd/src.git
synced 2024-12-21 23:18:00 -08:00
Show expensive mbuf operations in netstat(1) statistics.
If the memory layout is not optimal, m_defrag(), m_prepend(), m_pullup(), and m_pulldown() will allocate mbufs or copy memory. Count these operations to find possible optimizations. input dhill@; OK mvs@
This commit is contained in:
parent
1f3d741282
commit
5b00b7dda8
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kern_sysctl.c,v 1.445 2024/08/26 08:24:25 mvs Exp $ */
|
||||
/* $OpenBSD: kern_sysctl.c,v 1.446 2024/08/29 10:44:40 bluhm Exp $ */
|
||||
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
|
||||
|
||||
/*-
|
||||
@ -530,7 +530,6 @@ kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
|
||||
return (sysctl_rdstruct(oldp, oldlenp, newp, &bt, sizeof bt));
|
||||
}
|
||||
case KERN_MBSTAT: {
|
||||
extern struct cpumem *mbstat;
|
||||
uint64_t counters[MBSTAT_COUNT];
|
||||
struct mbstat mbs;
|
||||
unsigned int i;
|
||||
@ -543,6 +542,12 @@ kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
|
||||
mbs.m_drops = counters[MBSTAT_DROPS];
|
||||
mbs.m_wait = counters[MBSTAT_WAIT];
|
||||
mbs.m_drain = counters[MBSTAT_DRAIN];
|
||||
mbs.m_defrag_alloc = counters[MBSTAT_DEFRAG_ALLOC];
|
||||
mbs.m_prepend_alloc = counters[MBSTAT_PREPEND_ALLOC];
|
||||
mbs.m_pullup_alloc = counters[MBSTAT_PULLUP_ALLOC];
|
||||
mbs.m_pullup_copy = counters[MBSTAT_PULLUP_COPY];
|
||||
mbs.m_pulldown_alloc = counters[MBSTAT_PULLDOWN_ALLOC];
|
||||
mbs.m_pulldown_copy = counters[MBSTAT_PULLDOWN_COPY];
|
||||
|
||||
return (sysctl_rdstruct(oldp, oldlenp, newp,
|
||||
&mbs, sizeof(mbs)));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: uipc_mbuf.c,v 1.290 2024/03/05 18:52:41 bluhm Exp $ */
|
||||
/* $OpenBSD: uipc_mbuf.c,v 1.291 2024/08/29 10:44:40 bluhm Exp $ */
|
||||
/* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */
|
||||
|
||||
/*
|
||||
@ -234,8 +234,6 @@ struct mbuf *
|
||||
m_get(int nowait, int type)
|
||||
{
|
||||
struct mbuf *m;
|
||||
struct counters_ref cr;
|
||||
uint64_t *counters;
|
||||
int s;
|
||||
|
||||
KASSERT(type >= 0 && type < MT_NTYPES);
|
||||
@ -245,9 +243,7 @@ m_get(int nowait, int type)
|
||||
return (NULL);
|
||||
|
||||
s = splnet();
|
||||
counters = counters_enter(&cr, mbstat);
|
||||
counters[type]++;
|
||||
counters_leave(&cr, mbstat);
|
||||
counters_inc(mbstat, type);
|
||||
splx(s);
|
||||
|
||||
m->m_type = type;
|
||||
@ -267,8 +263,6 @@ struct mbuf *
|
||||
m_gethdr(int nowait, int type)
|
||||
{
|
||||
struct mbuf *m;
|
||||
struct counters_ref cr;
|
||||
uint64_t *counters;
|
||||
int s;
|
||||
|
||||
KASSERT(type >= 0 && type < MT_NTYPES);
|
||||
@ -278,9 +272,7 @@ m_gethdr(int nowait, int type)
|
||||
return (NULL);
|
||||
|
||||
s = splnet();
|
||||
counters = counters_enter(&cr, mbstat);
|
||||
counters[type]++;
|
||||
counters_leave(&cr, mbstat);
|
||||
counters_inc(mbstat, type);
|
||||
splx(s);
|
||||
|
||||
m->m_type = type;
|
||||
@ -417,17 +409,13 @@ struct mbuf *
|
||||
m_free(struct mbuf *m)
|
||||
{
|
||||
struct mbuf *n;
|
||||
struct counters_ref cr;
|
||||
uint64_t *counters;
|
||||
int s;
|
||||
|
||||
if (m == NULL)
|
||||
return (NULL);
|
||||
|
||||
s = splnet();
|
||||
counters = counters_enter(&cr, mbstat);
|
||||
counters[m->m_type]--;
|
||||
counters_leave(&cr, mbstat);
|
||||
counters_dec(mbstat, m->m_type);
|
||||
splx(s);
|
||||
|
||||
n = m->m_next;
|
||||
@ -557,6 +545,7 @@ m_defrag(struct mbuf *m, int how)
|
||||
|
||||
KASSERT(m->m_flags & M_PKTHDR);
|
||||
|
||||
counters_inc(mbstat, MBSTAT_DEFRAG_ALLOC);
|
||||
if ((m0 = m_gethdr(how, m->m_type)) == NULL)
|
||||
return (ENOBUFS);
|
||||
if (m->m_pkthdr.len > MHLEN) {
|
||||
@ -616,6 +605,7 @@ m_prepend(struct mbuf *m, int len, int how)
|
||||
m->m_data -= len;
|
||||
m->m_len += len;
|
||||
} else {
|
||||
counters_inc(mbstat, MBSTAT_PREPEND_ALLOC);
|
||||
MGET(mn, how, m->m_type);
|
||||
if (mn == NULL) {
|
||||
m_freem(m);
|
||||
@ -956,8 +946,8 @@ m_pullup(struct mbuf *m0, int len)
|
||||
memmove(head, mtod(m0, caddr_t), m0->m_len);
|
||||
m0->m_data = head;
|
||||
}
|
||||
|
||||
len -= m0->m_len;
|
||||
counters_inc(mbstat, MBSTAT_PULLUP_COPY);
|
||||
} else {
|
||||
/* the first mbuf is too small or read-only, make a new one */
|
||||
space = adj + len;
|
||||
@ -968,6 +958,7 @@ m_pullup(struct mbuf *m0, int len)
|
||||
m0->m_next = m;
|
||||
m = m0;
|
||||
|
||||
counters_inc(mbstat, MBSTAT_PULLUP_ALLOC);
|
||||
MGET(m0, M_DONTWAIT, m->m_type);
|
||||
if (m0 == NULL)
|
||||
goto bad;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: uipc_mbuf2.c,v 1.45 2020/12/12 11:48:54 jan Exp $ */
|
||||
/* $OpenBSD: uipc_mbuf2.c,v 1.46 2024/08/29 10:44:40 bluhm Exp $ */
|
||||
/* $KAME: uipc_mbuf2.c,v 1.29 2001/02/14 13:42:10 itojun Exp $ */
|
||||
/* $NetBSD: uipc_mbuf.c,v 1.40 1999/04/01 00:23:25 thorpej Exp $ */
|
||||
|
||||
@ -66,6 +66,7 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/pool.h>
|
||||
#include <sys/percpu.h>
|
||||
#include <sys/mbuf.h>
|
||||
|
||||
extern struct pool mtagpool;
|
||||
@ -117,6 +118,7 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp)
|
||||
if (len <= n->m_len - off) {
|
||||
struct mbuf *mlast;
|
||||
|
||||
counters_inc(mbstat, MBSTAT_PULLDOWN_ALLOC);
|
||||
o = m_dup1(n, off, n->m_len - off, M_DONTWAIT);
|
||||
if (o == NULL) {
|
||||
m_freem(m);
|
||||
@ -158,6 +160,7 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp)
|
||||
*/
|
||||
if ((off == 0 || offp) && m_trailingspace(n) >= tlen &&
|
||||
!sharedcluster) {
|
||||
counters_inc(mbstat, MBSTAT_PULLDOWN_COPY);
|
||||
m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len);
|
||||
n->m_len += tlen;
|
||||
m_adj(n->m_next, tlen);
|
||||
@ -167,6 +170,7 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp)
|
||||
!sharedcluster && n->m_next->m_len >= tlen) {
|
||||
n->m_next->m_data -= hlen;
|
||||
n->m_next->m_len += hlen;
|
||||
counters_inc(mbstat, MBSTAT_PULLDOWN_COPY);
|
||||
memmove(mtod(n->m_next, caddr_t), mtod(n, caddr_t) + off, hlen);
|
||||
n->m_len -= hlen;
|
||||
n = n->m_next;
|
||||
@ -182,6 +186,7 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp)
|
||||
m_freem(m);
|
||||
return (NULL);
|
||||
}
|
||||
counters_inc(mbstat, MBSTAT_PULLDOWN_ALLOC);
|
||||
MGET(o, M_DONTWAIT, m->m_type);
|
||||
if (o && len > MLEN) {
|
||||
MCLGETL(o, M_DONTWAIT, len);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: mbuf.h,v 1.263 2024/04/14 20:46:27 bluhm Exp $ */
|
||||
/* $OpenBSD: mbuf.h,v 1.264 2024/08/29 10:44:40 bluhm Exp $ */
|
||||
/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */
|
||||
|
||||
/*
|
||||
@ -363,11 +363,17 @@ u_int mextfree_register(void (*)(caddr_t, u_int, void *));
|
||||
/* length to m_copy to copy all */
|
||||
#define M_COPYALL 1000000000
|
||||
|
||||
#define MBSTAT_TYPES MT_NTYPES
|
||||
#define MBSTAT_DROPS (MBSTAT_TYPES + 0)
|
||||
#define MBSTAT_WAIT (MBSTAT_TYPES + 1)
|
||||
#define MBSTAT_DRAIN (MBSTAT_TYPES + 2)
|
||||
#define MBSTAT_COUNT (MBSTAT_TYPES + 3)
|
||||
#define MBSTAT_TYPES MT_NTYPES
|
||||
#define MBSTAT_DROPS (MBSTAT_TYPES + 0)
|
||||
#define MBSTAT_WAIT (MBSTAT_TYPES + 1)
|
||||
#define MBSTAT_DRAIN (MBSTAT_TYPES + 2)
|
||||
#define MBSTAT_DEFRAG_ALLOC (MBSTAT_TYPES + 3)
|
||||
#define MBSTAT_PREPEND_ALLOC (MBSTAT_TYPES + 4)
|
||||
#define MBSTAT_PULLUP_ALLOC (MBSTAT_TYPES + 5)
|
||||
#define MBSTAT_PULLUP_COPY (MBSTAT_TYPES + 6)
|
||||
#define MBSTAT_PULLDOWN_ALLOC (MBSTAT_TYPES + 7)
|
||||
#define MBSTAT_PULLDOWN_COPY (MBSTAT_TYPES + 8)
|
||||
#define MBSTAT_COUNT (MBSTAT_TYPES + 9)
|
||||
|
||||
/*
|
||||
* Mbuf statistics.
|
||||
@ -378,8 +384,14 @@ struct mbstat {
|
||||
u_long m_drops; /* times failed to find space */
|
||||
u_long m_wait; /* times waited for space */
|
||||
u_long m_drain; /* times drained protocols for space */
|
||||
u_long m_mtypes[MBSTAT_COUNT];
|
||||
u_long m_mtypes[MBSTAT_TYPES];
|
||||
/* type specific mbuf allocations */
|
||||
u_long m_defrag_alloc;
|
||||
u_long m_prepend_alloc;
|
||||
u_long m_pullup_alloc;
|
||||
u_long m_pullup_copy;
|
||||
u_long m_pulldown_alloc;
|
||||
u_long m_pulldown_copy;
|
||||
};
|
||||
|
||||
#include <sys/mutex.h>
|
||||
@ -404,6 +416,7 @@ extern long nmbclust; /* limit on the # of clusters */
|
||||
extern int max_linkhdr; /* largest link-level header */
|
||||
extern int max_protohdr; /* largest protocol header */
|
||||
extern int max_hdr; /* largest link+protocol header */
|
||||
extern struct cpumem *mbstat; /* mbuf statistics counter */
|
||||
|
||||
void mbinit(void);
|
||||
void mbcpuinit(void);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: mbuf.c,v 1.45 2023/07/16 03:01:31 yasuoka Exp $ */
|
||||
/* $OpenBSD: mbuf.c,v 1.46 2024/08/29 10:44:40 bluhm Exp $ */
|
||||
/* $NetBSD: mbuf.c,v 1.9 1996/05/07 02:55:03 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
@ -79,7 +79,7 @@ static struct mbtypes {
|
||||
};
|
||||
|
||||
int nmbtypes = sizeof(mbstat.m_mtypes) / sizeof(u_long);
|
||||
bool seen[MBSTAT_COUNT]; /* "have we seen this type yet?" */
|
||||
bool seen[MBSTAT_TYPES]; /* "have we seen this type yet?" */
|
||||
|
||||
/*
|
||||
* Print mbuf statistics.
|
||||
@ -93,7 +93,7 @@ mbpr(void)
|
||||
struct mbtypes *mp;
|
||||
size_t size;
|
||||
|
||||
if (nmbtypes != MBSTAT_COUNT) {
|
||||
if (nmbtypes != MBSTAT_TYPES) {
|
||||
fprintf(stderr,
|
||||
"%s: unexpected change to mbstat; check source\n",
|
||||
__progname);
|
||||
@ -205,4 +205,10 @@ mbpr(void)
|
||||
printf("%lu requests for memory denied\n", mbstat.m_drops);
|
||||
printf("%lu requests for memory delayed\n", mbstat.m_wait);
|
||||
printf("%lu calls to protocol drain routines\n", mbstat.m_drain);
|
||||
printf("%lu defrag mbuf allocation\n", mbstat.m_defrag_alloc);
|
||||
printf("%lu prepend mbuf allocation\n", mbstat.m_prepend_alloc);
|
||||
printf("%lu pullup mbuf allocation\n", mbstat.m_pullup_alloc);
|
||||
printf("%lu pullup memory copy\n", mbstat.m_pullup_copy);
|
||||
printf("%lu pulldown mbuf allocation\n", mbstat.m_pulldown_alloc);
|
||||
printf("%lu pulldown memory copy\n", mbstat.m_pulldown_copy);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user