From 5b00b7dda8bfc7f198d3a27a858787dca0d81520 Mon Sep 17 00:00:00 2001 From: bluhm Date: Thu, 29 Aug 2024 10:44:40 +0000 Subject: [PATCH] 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@ --- sys/kern/kern_sysctl.c | 9 +++++++-- sys/kern/uipc_mbuf.c | 25 ++++++++----------------- sys/kern/uipc_mbuf2.c | 7 ++++++- sys/sys/mbuf.h | 27 ++++++++++++++++++++------- usr.bin/netstat/mbuf.c | 12 +++++++++--- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index d52ff485c60..e015b530563 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -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))); diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index fc7b515c83f..db942bfd7d6 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -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; diff --git a/sys/kern/uipc_mbuf2.c b/sys/kern/uipc_mbuf2.c index 25670aa00ca..6a4bdca56ab 100644 --- a/sys/kern/uipc_mbuf2.c +++ b/sys/kern/uipc_mbuf2.c @@ -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 #include #include +#include #include 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); diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index b458e0e897a..b8745b9cb53 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -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 @@ -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); diff --git a/usr.bin/netstat/mbuf.c b/usr.bin/netstat/mbuf.c index 6eeeebe96f2..7660f832630 100644 --- a/usr.bin/netstat/mbuf.c +++ b/usr.bin/netstat/mbuf.c @@ -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); } -- 2.20.1