Skip to content
This repository has been archived by the owner on Jun 22, 2024. It is now read-only.

Commit

Permalink
[NetBSD] speedup net_connections() with proper filtering in C (giampa…
Browse files Browse the repository at this point in the history
…olo#2342)

Modify psutil.net_connections() to retrieving unnecessary connection types unless explicitly asked. E.g., on an IDLE system with few IPv6 connections this will run around 170% faster:

```
import psutil, time
started = time.monotonic()
for x in range(1000):
    psutil.net_connections("tcp6")
print(f"completed in {(time.monotonic() - started):.4f} secs")
```

Before all connection types (TCP, UDP, UNIX) were retrived internally, even if they were not returned.
  • Loading branch information
giampaolo authored Dec 20, 2023
1 parent ad24d6c commit cb3ab37
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 102 deletions.
14 changes: 14 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
5.9.8 (IN DEVELOPMENT)
======================

**Enhancements**

- 2342_, [NetBSD]: filter `net_connections()`_ returned list in C instead of
Python, and avoid to retrieve unnecessary connection types unless explicitly
asked. E.g., on an IDLE system with few IPv6 connections this will run around
170% faster. Before all connection types (TCP, UDP, UNIX) were retrived
internally, even if they were not returned.::

import psutil, time
started = time.monotonic()
for x in range(1000):
psutil.net_connections("tcp6")
print(f"completed in {(time.monotonic() - started):.4f} secs")

**Bug fixes**

- 930_, [NetBSD], [critical]: `net_connections()`_ implementation was broken.
Expand Down
12 changes: 5 additions & 7 deletions psutil/_psbsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,14 +426,13 @@ def net_connections(kind):
if OPENBSD:
rawlist = cext.net_connections(-1, families, types)
elif NETBSD:
rawlist = cext.net_connections(-1)
rawlist = cext.net_connections(-1, kind)
else: # FreeBSD
rawlist = cext.net_connections()

for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
if NETBSD or FREEBSD:
# OpenBSD implements filtering in C
if FREEBSD:
if (fam not in families) or (type not in types):
continue
nt = conn_to_ntuple(fd, fam, type, laddr, raddr,
Expand Down Expand Up @@ -786,16 +785,15 @@ def connections(self, kind='inet'):
ret = []

if NETBSD:
rawlist = cext.net_connections(self.pid)
rawlist = cext.net_connections(self.pid, kind)
elif OPENBSD:
rawlist = cext.net_connections(self.pid, families, types)
else: # FreeBSD
else:
rawlist = cext.proc_connections(self.pid, families, types)

for item in rawlist:
fd, fam, type, laddr, raddr, status = item[:6]
if NETBSD:
# FreeBSD and OpenBSD implement filtering in C
if FREEBSD:
if (fam not in families) or (type not in types):
continue
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status,
Expand Down
178 changes: 83 additions & 95 deletions psutil/arch/netbsd/socks.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,6 @@
#include "../../_psutil_posix.h"


// address family filter
enum af_filter {
INET,
INET4,
INET6,
TCP,
TCP4,
TCP6,
UDP,
UDP4,
UDP6,
UNIX,
ALL,
};

// kinfo_file results
struct kif {
SLIST_ENTRY(kif) kifs;
Expand Down Expand Up @@ -245,84 +230,85 @@ psutil_get_sockets(const char *name) {

// Collect open file and connections.
static int
psutil_get_info(int aff) {
switch (aff) {
case INET:
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
break;
case INET4:
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
break;
case INET6:
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
break;
case TCP:
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
break;
case TCP4:
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
break;
case TCP6:
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
break;
case UDP:
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
break;
case UDP4:
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
break;
case UDP6:
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
break;
case UNIX:
if (psutil_get_sockets("net.local.stream.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.seqpacket.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.dgram.pcblist") != 0)
return -1;
break;
case ALL:
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.stream.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.seqpacket.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.dgram.pcblist") != 0)
return -1;
break;
psutil_get_info(char *kind) {
if (strcmp(kind, "inet") == 0) {
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
}
else if (strcmp(kind, "inet4") == 0) {
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
}
else if (strcmp(kind, "inet6") == 0) {
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
}
else if (strcmp(kind, "tcp") == 0) {
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
}
else if (strcmp(kind, "tcp4") == 0) {
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
}
else if (strcmp(kind, "tcp6") == 0) {
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
}
else if (strcmp(kind, "udp") == 0) {
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
}
else if (strcmp(kind, "udp4") == 0) {
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
}
else if (strcmp(kind, "udp6") == 0) {
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
}
else if (strcmp(kind, "unix") == 0) {
if (psutil_get_sockets("net.local.stream.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.seqpacket.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.dgram.pcblist") != 0)
return -1;
}
else if (strcmp(kind, "all") == 0) {
if (psutil_get_sockets("net.inet.tcp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet.udp.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.stream.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.seqpacket.pcblist") != 0)
return -1;
if (psutil_get_sockets("net.local.dgram.pcblist") != 0)
return -1;
}
else {
PyErr_SetString(PyExc_ValueError, "invalid kind value");
return -1;
}

return 0;
}

Expand All @@ -334,6 +320,7 @@ PyObject *
psutil_net_connections(PyObject *self, PyObject *args) {
char laddr[PATH_MAX];
char raddr[PATH_MAX];
char *kind;
int32_t lport;
int32_t rport;
int32_t status;
Expand All @@ -346,15 +333,16 @@ psutil_net_connections(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;

if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (! PyArg_ParseTuple(args, _Py_PARSE_PID "s", &pid, &kind)) {
goto error;
}

psutil_kiflist_init();
psutil_kpcblist_init();

if (psutil_get_files() != 0)
goto error;
if (psutil_get_info(ALL) != 0)
if (psutil_get_info(kind) != 0)
goto error;

struct kif *k;
Expand Down

0 comments on commit cb3ab37

Please sign in to comment.