[LINUX] Beschleunigen Sie den Befehl netstat

Einführung

Es ist eine Geschichte, dass der Befehl netstat schneller wurde, wenn der Linux-Kernel und der Befehl netstat leicht modifiziert wurden.

Überblick

Umgebung

$ uname -r
3.10.0-693.17.1.el7.x86_64
$ rpm -q kernel
kernel-3.10.0-693.11.6.el7.x86_64
kernel-3.10.0-693.17.1.el7.x86_64
$ rpm -q net-tools
net-tools-2.0-0.22.20131004git.el7.x86_64

$ cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
$ LANG=C lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                2
On-line CPU(s) list:   0,1
Thread(s) per core:    2
Core(s) per socket:    1
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 63
Model name:            Intel(R) Xeon(R) CPU E5-2673 v3 @ 2.40GHz
Stepping:              2
CPU MHz:               2394.456
BogoMIPS:              4788.91
Virtualization:        VT-x
Hypervisor vendor:     Microsoft
Virtualization type:   full
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              30720K
NUMA node0 CPU(s):     0,1
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq vmx ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm tpr_shadow vnmi ept vpid fsgsbase bmi1 avx2 smep bmi2 erms xsaveopt
$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7966         416        6876           8         673        7205
Swap:             0           0           0

Verfahren

Vorbereitung

--Installieren und konfigurieren Sie verschiedene Elemente, die zum Erstellen des RPM-Pakets erforderlich sind

sudo useradd mockbuild
sudo yum -y install rpm-build
sudo yum -y groups install "Development Tools"

Befreien Sie sich von dem Linux-Kernel

Beziehen und installieren Sie SRPM des Kernels

yumdownloader --source kernel
rpm -ivh kernel-3.10.0-693.17.1.el7.centos.plus.src.rpm
sudo yum -y install m4 gcc xmlto asciidoc hmaccalc  python-devel newt-devel 'perl(ExtUtils::Embed)' pesign elfutils-devel zlib-devel binutils-devel bison audit-libs-devel  java-devel openssl-devel numactl-devel pciutils-devel ncurses-devel

Bereiten Sie die Patch & Fix-SPEC-Datei vor

--Erstellen Sie einen Patch mit dem folgenden Inhalt als "~ / rpmbuild / SOURCES / proc-net-tcp.patch"

--- a/net/ipv4/tcp_ipv4.c	2018-01-14 15:02:54.000000000 +0000
+++ b/net/ipv4/tcp_ipv4.c	2018-02-10 06:08:39.043951339 +0000
@@ -2382,10 +2382,21 @@
 	return 0;
 }
 
+static ssize_t tcp_seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
+{
+	struct seq_file *m = file->private_data;
+	if (!m->buf) {
+		m->buf = kmalloc( m->size = 16 * PAGE_SIZE, GFP_KERNEL);
+		if (!m->buf)
+			return -ENOMEM;
+	}
+	return seq_read(file, buf, size, ppos);
+}
+
 static const struct file_operations tcp_afinfo_seq_fops = {
 	.owner   = THIS_MODULE,
 	.open    = tcp_seq_open,
-	.read    = seq_read,
+	.read    = tcp_seq_read,
 	.llseek  = seq_lseek,
 	.release = seq_release_net
 };
--- a/net/ipv6/tcp_ipv6.c	2018-01-14 15:02:54.000000000 +0000
+++ b/net/ipv6/tcp_ipv6.c	2018-02-10 06:10:39.910935928 +0000
@@ -1812,10 +1812,21 @@
 	return 0;
 }
 
+static ssize_t tcp_seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
+{
+	struct seq_file *m = file->private_data;
+	if (!m->buf) {
+		m->buf = kmalloc( m->size = 16 * PAGE_SIZE, GFP_KERNEL);
+		if (!m->buf)
+			return -ENOMEM;
+	}
+	return seq_read(file, buf, size, ppos);
+}
+
 static const struct file_operations tcp6_afinfo_seq_fops = {
 	.owner   = THIS_MODULE,
 	.open    = tcp_seq_open,
-	.read    = seq_read,
+	.read    = tcp_seq_read,
 	.llseek  = seq_lseek,
 	.release = seq_release_net
 };

$ diff ~/rpmbuild/SPECS/kernel.spec.org ~/rpmbuild/SPECS/kernel.spec
8c8
< %define buildid .centos.plus
---
> %define buildid .procnettcp
463a464,465
> Patch50000: proc-net-tcp.patch
>
832a835,836
>
> ApplyPatch proc-net-tcp.patch

Erstellen Sie ein Linux-Kernelpaket

――Die in der diesmal verwendeten Umgebung benötigte Zeit beträgt mehr als 1,5 Stunden

rpmbuild -ba ~/rpmbuild/SPECS/kernel.spec
find ~/rpmbuild/ -name "*.rpm"

Ergebnis

Bestätigung mit dem Befehl cat

--Für den Befehl cat, der den Inhalt von / proc / net / tcp liest, verwenden Sie den Befehl strace, um den Status des Aufrufs des gelesenen Systems zu beobachten.

$ uname -r
3.10.0-693.17.1.el7.procnettcp.x86_64
$ LANG=C strace -e open,read cat /proc/net/tcp|wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY)         = 3
read(3, "  sl  local_address rem_address "..., 65536) = 11700
read(3, "", 65536)                      = 0
78
+++ exited with 0 +++
$ uname -r
3.10.0-693.17.1.el7.x86_64
$ LANG=C strace -e open,read cat /proc/net/tcp|wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY)         = 3
read(3, "  sl  local_address rem_address "..., 65536) = 4050
read(3, "  26: 0502010A:861A 10813FA8:005"..., 65536) = 1650
read(3, "", 65536)                      = 0
38
+++ exited with 0 +++

Bestätigung mit dem Befehl netstat

$ uname -r
3.10.0-693.17.1.el7.procnettcp.x86_64
$ LANG=C strace -e open,read netstat -atn |wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300j\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360\25\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\16\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0m\0\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY)         = 3
read(3, "  sl  local_address rem_address "..., 4096) = 4096
read(3, "00000000 03:00001608 00000000   "..., 4096) = 4096
read(3, " 3 ffff880287e55d00             "..., 4096) = 4096
read(3, "           \n", 4096)          = 12
read(3, "", 4096)                       = 0
open("/proc/net/tcp6", O_RDONLY)        = 3
read(3, "  sl  local_address             "..., 4096) = 853
read(3, "", 4096)                       = 0
+++ exited with 0 +++
87
$ uname -r
3.10.0-693.17.1.el7.x86_64
$ LANG=C strace -e open,read netstat -atn |wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300j\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360\25\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\16\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0m\0\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY)         = 3
read(3, "  sl  local_address rem_address "..., 4096) = 4050
read(3, "  26: 0502010A:870C 10813FA8:005"..., 4096) = 4050
read(3, "  53: 0502010A:E488 19E57328:01B"..., 4096) = 900
read(3, "", 4096)                       = 0
open("/proc/net/tcp6", O_RDONLY)        = 3
read(3, "  sl  local_address             "..., 4096) = 676
read(3, "", 4096)                       = 0
+++ exited with 0 +++
64

Netstat loswerden

Holen und installieren Sie SRPM von Net-Tools

yumdownloader --source net-tools
rpm -ivh net-tools-2.0-0.22.20131004git.el7.src.rpm
sudo yum -y install libselinux-devel

Bereiten Sie die Patch & Fix-SPEC-Datei vor

--Erstellen Sie einen Patch mit dem folgenden Inhalt als "~ / rpmbuild / SOURCES / net-tools-netstat-proc-net-tcp-buffer-size.patch"

--- a/lib/proc.c	2013-09-30 08:07:32.000000000 +0000
+++ b/lib/proc.c	2018-02-11 04:48:40.959339035 +0000
@@ -88,9 +88,9 @@
 
     if (!buffer) {
       pagesz = getpagesize();
-      buffer = malloc(pagesz);
+      buffer = malloc(16*pagesz);
     }
 
-    setvbuf(fd, buffer, _IOFBF, pagesz);
+    setvbuf(fd, buffer, _IOFBF, 16*pagesz);
     return fd;
 }
$ diff ~/rpmbuild/SPECS/net-tools.spec.org  ~/rpmbuild/SPECS/net-tools.spec
67a68,69
> Patch100: net-tools-netstat-proc-net-tcp-buffer-size.patch
>
104a107,108
>
> %patch100 -p1 -b .proc-net-tcp

Erstellen Sie ein Net-Tools-Paket

rpmbuild -bb ~/rpmbuild/SPECS/net-tools.spec
ls -l ~/rpmbuild/BUILD/net-tools/netstat 

Ergebnis

$ LANG=C strace -e open,read netstat -atn  |wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300j\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360\25\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\16\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0m\0\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY)         = 3
read(3, "  sl  local_address rem_address "..., 4096) = 4096
read(3, "00000000 03:0000022B 00000000   "..., 4096) = 4096
read(3, " 3 ffff8802c43a7d00             "..., 4096) = 3508
read(3, "", 4096)                       = 0
open("/proc/net/tcp6", O_RDONLY)        = 3
read(3, "  sl  local_address             "..., 4096) = 853
read(3, "", 4096)                       = 0
+++ exited with 0 +++
83
$ LANG=C strace -e open,read ~/rpmbuild/BUILD/net-tools-2.0/netstat -atn  |wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300j\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360\25\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\16\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0m\0\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY)         = 3
read(3, "  sl  local_address rem_address "..., 65536) = 11700
read(3, "", 65536)                      = 0
open("/proc/net/tcp6", O_RDONLY)        = 3
read(3, "  sl  local_address             "..., 65536) = 853
read(3, "", 65536)                      = 0
+++ exited with 0 +++
83

Vergleich des Verhaltens mit vielen TCP-Sitzungen

--Verwenden Sie Apache und den Befehl ab des mit Apache gelieferten Benchmark-Tools, um die Anzahl der TCP-Sitzungen zu erhöhen --Vergleichen Sie die Operation des Befehls netstat vor und nach der Änderung, während Sie den Einzeiler ausführen, der Apache installiert und startet und den Befehl ab wiederholt ausführt.

sudo yum -y install httpd
sudo systemctl start  httpd.service
while : ; do ab -n 100000 -c 1000 127.0.0.1/test; done
$ time  netstat -atn |wc -l
16528

real    0m0.355s
user    0m0.110s
sys     0m0.254s
$ time  ~/rpmbuild/BUILD/net-tools-2.0/netstat  -atn |wc -l
16202

real    0m0.133s
user    0m0.115s
sys     0m0.027s

Schließlich

[^ ss-using-procfs]: Wenn die Erfassung von Informationen durch Netlink fehlschlägt, werden die Informationen mithilfe von procfs erfasst.

$ time  ss -atn |wc -l
15922

real    0m0.046s
user    0m0.033s
sys     0m0.021s

In Anbetracht dessen, dass der Befehl netstat oder die net-tools als veraltet angesehen werden, ist es besser, den Befehl ss gehorsam zu verwenden.

Recommended Posts

Beschleunigen Sie den Befehl netstat
Über den Servicebefehl
Installieren Sie den Befehl pip
python3 Messen Sie die Verarbeitungsgeschwindigkeit.
Was ich getan habe, um die String-Suchaufgabe zu beschleunigen
Klonen Sie mit dem Befehl dd
Bis die Shell den Befehl findet
Ein Befehl zum einfachen Überprüfen der Netzwerkgeschwindigkeit auf der Konsole
Numba als Python zu beschleunigen
Tauche ein in den Django Custom Befehl [1]
Befehl mv Eine Ebene nach oben gehen
Im Python-Befehl zeigt Python auf Python3.8
Befehl [linux] kill, um den Prozess abzubrechen
Lassen Sie Python die Befehlsausgabe lesen
Beschleunigen Sie Python mit numba grob
Project Euler 4 Versuch zu beschleunigen
So beschleunigen Sie Python-Berechnungen
Der Befehl hostname kann multifunktional sein
Drücken Sie den obersten Befehl mit htop
[DRF] Snippet zur Beschleunigung von PrimaryKeyRelatedField
Beschleunigen Sie die C / C ++ - Kompilierung mit ccache
Befehl für das aktuelle Verzeichnis Python
Suchen Sie in der Befehlszeile nach dem Wi-Fi-Netzwerknamen (SSID) Ihres Mac