portlist: remove unix.Readlink allocs on Linux

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>
This commit is contained in:
Brad Fitzpatrick 2022-10-22 11:21:10 -07:00 committed by Brad Fitzpatrick
parent 7149155b80
commit 3697609aaa
2 changed files with 26 additions and 3 deletions

View File

@ -243,7 +243,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/net/tunstats from tailscale.com/net/tstun+
tailscale.com/net/wsconn from tailscale.com/control/controlhttp+
tailscale.com/paths from tailscale.com/ipn/ipnlocal+
tailscale.com/portlist from tailscale.com/ipn/ipnlocal
💣 tailscale.com/portlist from tailscale.com/ipn/ipnlocal
tailscale.com/safesocket from tailscale.com/client/tailscale+
tailscale.com/smallzstd from tailscale.com/ipn/ipnserver+
LD 💣 tailscale.com/ssh/tailssh from tailscale.com/cmd/tailscaled

View File

@ -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
}