The following reply was made to PR kern/167204; it has been noted by GNATS.
From: Jilles Tjoelker
To: bug-follo...@freebsd.org, eu...@grosbein.net
Cc: "Eugene M. Zheganin"
Subject: Re: kern/167204: [kernel] terrible "netstat -rn" performance due to
slow kvm_nlist()
Date: Sun, 20 Oct 2013 00:15:33 +0200
In PR kern/167204, you wrote:
> ['netstat -rn' is extremely slow]
On a machine here with a faster CPU, 'netstat -rn' takes about 100ms
which I still consider very slow.
I see two main causes of the slowness here:
* kldsym(2) is very slow, particularly if debug symbols are loaded or on
architectures such as amd64 that use 'ELF relocatable' as their kld
module format (architectures such as i386 use 'ELF shared object'
which has a hash table for non-debug symbols).
* netstat(1) looks up all kernel symbols it could ever need, with all
possible compile options, when it needs any kernel symbol. This
appears to be the usual way to use libkvm but netstat is particularly
egregious in the number of kernel symbols it may need.
The below ugly patch (for head only; stable/10 has a simple conflict and
stable/9 is full of conflicts) ensures the '-r' and '-rs' modes only
look up the symbols necessary. This speeds up those modes considerably.
Index: usr.bin/netstat/main.c
===
--- usr.bin/netstat/main.c (revision 256728)
+++ usr.bin/netstat/main.c (working copy)
@@ -69,100 +69,108 @@
#include
#include "netstat.h"
+static struct nlist rs_nl[] = {
+#define RS_N_RTSTAT 0
+ { .n_name = "_rtstat" },
+#define RS_N_RTTRASH1
+ { .n_name = "_rttrash" },
+ { .n_name = NULL },
+};
+
+static struct nlist r_nl[] = {
+#define R_N_RTREE 0
+ { .n_name = "_rt_tables"},
+ { .n_name = NULL },
+};
+
static struct nlist nl[] = {
#define N_IFNET 0
{ .n_name = "_ifnet" }, /* XXXGL: can be deleted */
-#define N_RTSTAT1
- { .n_name = "_rtstat" },
-#define N_RTREE 2
- { .n_name = "_rt_tables"},
-#define N_MRTSTAT 3
+#define N_MRTSTAT 1
{ .n_name = "_mrtstat" },
-#define N_MFCHASHTBL4
+#define N_MFCHASHTBL2
{ .n_name = "_mfchashtbl" },
-#define N_VIFTABLE 5
+#define N_VIFTABLE 3
{ .n_name = "_viftable" },
-#define N_IPX 6
+#define N_IPX 3
{ .n_name = "_ipxpcb_list"},
-#define N_IPXSTAT 7
+#define N_IPXSTAT 4
{ .n_name = "_ipxstat"},
-#define N_SPXSTAT 8
+#define N_SPXSTAT 5
{ .n_name = "_spx_istat"},
-#define N_DDPSTAT 9
+#define N_DDPSTAT 6
{ .n_name = "_ddpstat"},
-#define N_DDPCB 10
+#define N_DDPCB 7
{ .n_name = "_ddpcb"},
-#define N_NGSOCKS 11
+#define N_NGSOCKS 8
{ .n_name = "_ngsocklist"},
-#define N_IP6STAT 12
+#define N_IP6STAT 9
{ .n_name = "_ip6stat" },
-#define N_ICMP6STAT 13
+#define N_ICMP6STAT 10
{ .n_name = "_icmp6stat" },
-#define N_IPSECSTAT 14
+#define N_IPSECSTAT 11
{ .n_name = "_ipsec4stat" },
-#define N_IPSEC6STAT15
+#define N_IPSEC6STAT12
{ .n_name = "_ipsec6stat" },
-#define N_PIM6STAT 16
+#define N_PIM6STAT 13
{ .n_name = "_pim6stat" },
-#define N_MRT6STAT 17
+#define N_MRT6STAT 14
{ .n_name = "_mrt6stat" },
-#define N_MF6CTABLE 18
+#define N_MF6CTABLE 15
{ .n_name = "_mf6ctable" },
-#define N_MIF6TABLE 19
+#define N_MIF6TABLE 16
{ .n_name = "_mif6table" },
-#define N_PFKEYSTAT 20
+#define N_PFKEYSTAT 17
{ .n_name = "_pfkeystat" },
-#define N_RTTRASH 21
- { .n_name = "_rttrash" },
-#define N_CARPSTAT 22
+#define N_CARPSTAT 19
{ .n_name = "_carpstats" },
-#define N_PFSYNCSTAT23
+#define N_PFSYNCSTAT20
{ .n_name = "_pfsyncstats" },
-#define N_AHSTAT24
+#define N_AHSTAT21
{ .n_name = "_ahstat" },
-#define N_ESPSTAT 25
+#define N_ESPSTAT 22
{ .n_name = "_espstat" },
-#define N_IPCOMPSTAT26
+#define N_IPCOMPSTAT23
{ .n_name = "_ipcompstat" },
-#define N_TCPSTAT 27
+#define N_TCPSTAT 24
{ .n_name = "_tcpstat" },
-#define N_UDPSTAT 28
+#define N_UDPSTAT 25
{ .n_name = "_udpstat" },
-#define N_IPSTAT29
+#define N_IPSTAT26
{ .n_name = "_ipstat" },
-#define N_ICMPSTAT 30
+#define N_ICM