Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
more mbuf counter
To:
tech@openbsd.org
Date:
Wed, 28 Aug 2024 20:31:35 +0200

Download raw body.

Thread
  • Alexander Bluhm:

    more mbuf counter

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?

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);
 }