From 6d2dd355e17f758cfda01ab376fd388dc717f096 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sat, 22 Oct 2022 11:21:10 -0700 Subject: [PATCH] portlist: remove unix.Readlink allocs on Linux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta GetList-8 11.2ms ± 5% 11.1ms ± 3% ~ (p=0.661 n=10+9) name old alloc/op new alloc/op delta GetList-8 83.3kB ± 1% 67.4kB ± 1% -19.05% (p=0.000 n=10+10) name old allocs/op new allocs/op delta GetList-8 2.89k ± 2% 2.19k ± 1% -24.24% (p=0.000 n=10+10) (real issue is we're calling this code as much as we are, but easy enough to make it efficient because it'll still need to be called sometimes in any case) Updates #5958 Change-Id: I90c20278d73e80315a840aed1397d24faa308d93 Signed-off-by: Brad Fitzpatrick --- portlist/portlist_linux.go | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/portlist/portlist_linux.go b/portlist/portlist_linux.go index a40fb9909fd9a..4d5faabbfdea1 100644 --- a/portlist/portlist_linux.go +++ b/portlist/portlist_linux.go @@ -18,6 +18,7 @@ import ( "sync/atomic" "syscall" "time" + "unsafe" "go4.org/mem" "golang.org/x/sys/unix" @@ -215,6 +216,8 @@ func addProcesses(pl []Port) ([]Port, error) { pm[pl[i].inode] = &pl[i] } + var pathBuf []byte + err := foreachPID(func(pid string) error { fdPath := fmt.Sprintf("/proc/%s/fd", pid) @@ -251,8 +254,9 @@ func addProcesses(pl []Port) ([]Port, error) { return fmt.Errorf("addProcesses.readDir: %w", err) } for _, fd := range fds { - n, err := unix.Readlink(fmt.Sprintf("/proc/%s/fd/%s", pid, fd), targetBuf) - if err != nil { + pathBuf = fmt.Appendf(pathBuf[:0], "/proc/%s/fd/%s\x00", pid, fd) + n, ok := readlink(pathBuf, targetBuf) + if !ok { // Not a symlink or no permission. // Skip it. continue @@ -337,3 +341,22 @@ func fieldIndex(line []byte, n int) int { } return skip } + +// path must be null terminated. +func readlink(path, buf []byte) (n int, ok bool) { + if len(buf) == 0 || len(path) < 2 || path[len(path)-1] != 0 { + return 0, false + } + var dirfd int = unix.AT_FDCWD + r0, _, e1 := unix.Syscall6(unix.SYS_READLINKAT, + uintptr(dirfd), + uintptr(unsafe.Pointer(&path[0])), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(len(buf)), + 0, 0) + n = int(r0) + if e1 != 0 { + return 0, false + } + return n, true +}