From: Vitaliy Makkoveev Subject: Re: more mbuf counter To: Alexander Bluhm Cc: tech@openbsd.org Date: Wed, 28 Aug 2024 21:41:42 +0300 > On 28 Aug 2024, at 21:31, Alexander Bluhm wrote: > > Hi, > > I want to figure out when expensive operations on mbufs happen. If > the memory layout is not optimal, m_defrag(), m_prepend(), m_pullup(), > and m_pulldown() will allocate mbufs or copy memory. I want to > count these operations to find possible optimizations. > > netstat -m now shows: > > 667 mbufs in use: > 432 mbufs allocated to data > 225 mbufs allocated to packet headers > 10 mbufs allocated to socket names and addresses > 207/296 mbuf 2048 byte clusters in use (current/peak) > 0/60 mbuf 2112 byte clusters in use (current/peak) > 0/24 mbuf 4096 byte clusters in use (current/peak) > 0/16 mbuf 8192 byte clusters in use (current/peak) > 0/14 mbuf 9216 byte clusters in use (current/peak) > 0/10 mbuf 12288 byte clusters in use (current/peak) > 0/16 mbuf 16384 byte clusters in use (current/peak) > 0/248 mbuf 65536 byte clusters in use (current/peak) > 10400/17600/8000000 Kbytes allocated to network (current/peak/max) > 0 requests for memory denied > 0 requests for memory delayed > 0 calls to protocol drain routines > 125 defrag mbuf allocation > 141 prepend mbuf allocation > 0 pullup mbuf allocation > 0 pullup memory copy > 0 pulldown mbuf allocation > 0 pulldown memory copy > > ok? > Sure. > bluhm > > Index: sys/kern/kern_sysctl.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_sysctl.c,v > diff -u -p -r1.445 kern_sysctl.c > --- sys/kern/kern_sysctl.c 26 Aug 2024 08:24:25 -0000 1.445 > +++ sys/kern/kern_sysctl.c 28 Aug 2024 12:09:45 -0000 > @@ -530,7 +530,6 @@ kern_sysctl(int *name, u_int namelen, vo > 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, vo > 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))); > Index: sys/kern/uipc_mbuf.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_mbuf.c,v > diff -u -p -r1.290 uipc_mbuf.c > --- sys/kern/uipc_mbuf.c 5 Mar 2024 18:52:41 -0000 1.290 > +++ sys/kern/uipc_mbuf.c 28 Aug 2024 11:42:15 -0000 > @@ -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 h > 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; > Index: sys/kern/uipc_mbuf2.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_mbuf2.c,v > diff -u -p -r1.45 uipc_mbuf2.c > --- sys/kern/uipc_mbuf2.c 12 Dec 2020 11:48:54 -0000 1.45 > +++ sys/kern/uipc_mbuf2.c 28 Aug 2024 12:12:19 -0000 > @@ -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 > 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 > */ > 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 > !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 > 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); > Index: sys/sys/mbuf.h > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/sys/sys/mbuf.h,v > diff -u -p -r1.263 mbuf.h > --- sys/sys/mbuf.h 14 Apr 2024 20:46:27 -0000 1.263 > +++ sys/sys/mbuf.h 28 Aug 2024 12:08:48 -0000 > @@ -363,11 +363,17 @@ u_int mextfree_register(void (*)(caddr_t > /* 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 + 10) > > /* > * 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 > 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); > Index: usr.bin/netstat/mbuf.c > =================================================================== > RCS file: /data/mirror/openbsd/cvs/src/usr.bin/netstat/mbuf.c,v > diff -u -p -r1.45 mbuf.c > --- usr.bin/netstat/mbuf.c 16 Jul 2023 03:01:31 -0000 1.45 > +++ usr.bin/netstat/mbuf.c 28 Aug 2024 12:21:15 -0000 > @@ -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); > } >