mirror of
https://github.com/tailscale/tailscale.git
synced 2026-09-14 23:11:39 -04:00
As of Linux 6.2 (torvalds/linux@f1f1f25699), the stat size of the /proc/self/fd directory is the number of open file descriptors, so CurrentFDs no longer needs to walk the directory on modern kernels. The walk is O(n) in the number of open file descriptors, which adds up on servers like derper that hold many connections and report this metric on every scrape: at 10k open fds, the walk takes about 2.2ms while an fstat takes a constant 300ns. We fstat a directory file descriptor held open for the process lifetime rather than calling stat with the path, because syscall.Stat copies the path string to a NUL-terminated buffer on every call and the metric must remain allocation-free. Kernels older than 6.2 report a size of zero, in which case we fall back to the directory walk. Updates #2784 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Change-Id: I1742db2ae1938c77f9b7d137b167ab4a2b6b6167
21 lines
540 B
Go
21 lines
540 B
Go
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package metrics
|
|
|
|
import "testing"
|
|
|
|
func TestCurrentFDsFast(t *testing.T) {
|
|
fast, ok := currentFDsFast()
|
|
if !ok {
|
|
t.Skip("fast path unavailable; kernel older than 6.2")
|
|
}
|
|
// The dirwalk count includes the directory file descriptor that
|
|
// the walk itself has open, so it reports one more than the fast
|
|
// path does.
|
|
slow := currentFDsDirwalk() - 1
|
|
if fast != slow {
|
|
t.Errorf("currentFDsFast = %v; currentFDsDirwalk-1 = %v", fast, slow)
|
|
}
|
|
}
|