Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[24.0 backport] pkg/fileutils: GetTotalUsedFds: reduce allocations #45856

Merged
merged 5 commits into from Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
52 changes: 52 additions & 0 deletions pkg/fileutils/fileutils_linux.go
@@ -0,0 +1,52 @@
package fileutils

import (
"context"
"fmt"
"io"
"os"

"github.com/containerd/containerd/log"
"golang.org/x/sys/unix"
)

// GetTotalUsedFds Returns the number of used File Descriptors by
// reading it via /proc filesystem.
func GetTotalUsedFds() int {
name := fmt.Sprintf("/proc/%d/fd", os.Getpid())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surprised you used Sprintf here :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha, yeah I was doubting, but in the total scheme of things, it was slightly more readable than strconv and path.Join combined


// Fast-path for Linux 6.2 (since [f1f1f2569901ec5b9d425f2e91c09a0e320768f3]).
// From the [Linux docs]:
//
// "The number of open files for the process is stored in 'size' member of
// stat() output for /proc/<pid>/fd for fast access."
//
// [Linux docs]: https://docs.kernel.org/filesystems/proc.html#proc-pid-fd-list-of-symlinks-to-open-files:
// [f1f1f2569901ec5b9d425f2e91c09a0e320768f3]: https://github.com/torvalds/linux/commit/f1f1f2569901ec5b9d425f2e91c09a0e320768f3
var stat unix.Stat_t
if err := unix.Stat(name, &stat); err == nil && stat.Size > 0 {
return int(stat.Size)
}

f, err := os.Open(name)
if err != nil {
log.G(context.TODO()).WithError(err).Error("Error listing file descriptors")
return -1
}
defer f.Close()

var fdCount int
for {
names, err := f.Readdirnames(100)
fdCount += len(names)
if err == io.EOF {
break
} else if err != nil {
log.G(context.TODO()).WithError(err).Error("Error listing file descriptors")
return -1
}
}
// Note that the slow path has 1 more file-descriptor, due to the open
// file-handle for /proc/<pid>/fd during the calculation.
return fdCount
}
7 changes: 7 additions & 0 deletions pkg/fileutils/fileutils_test.go
Expand Up @@ -240,3 +240,10 @@ func TestCreateIfNotExistsFile(t *testing.T) {
t.Errorf("Should have been a file, seems it's not")
}
}

func BenchmarkGetTotalUsedFds(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = GetTotalUsedFds()
}
}
22 changes: 0 additions & 22 deletions pkg/fileutils/fileutils_unix.go

This file was deleted.