Download raw body.
more mbuf counter
> On 28 Aug 2024, at 21:31, Alexander Bluhm <bluhm@openbsd.org> 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 <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
> 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 <sys/mutex.h>
> @@ -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);
> }
>
more mbuf counter