Skip to content

Commit

Permalink
portlist: remove unix.Readlink allocs on Linux
Browse files Browse the repository at this point in the history
    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 <bradfitz@tailscale.com>
  • Loading branch information
bradfitz committed Oct 22, 2022
1 parent 7149155 commit 6d2dd35
Showing 1 changed file with 25 additions and 2 deletions.
27 changes: 25 additions & 2 deletions portlist/portlist_linux.go
Expand Up @@ -18,6 +18,7 @@ import (
"sync/atomic"
"syscall"
"time"
"unsafe"

"go4.org/mem"
"golang.org/x/sys/unix"
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}

0 comments on commit 6d2dd35

Please sign in to comment.