mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-18 04:49:55 +00:00
Use Readdirnames to reduce number of stats we're doing.
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
// Interface is the filesystem interface type.
|
||||
type Interface interface {
|
||||
ReadDir(string) ([]os.FileInfo, error)
|
||||
ReadDirNames(string) ([]string, error)
|
||||
ReadFile(string) ([]byte, error)
|
||||
Lstat(string, *syscall.Stat_t) error
|
||||
Stat(string, *syscall.Stat_t) error
|
||||
@@ -25,6 +26,15 @@ func (realFS) ReadDir(path string) ([]os.FileInfo, error) {
|
||||
return ioutil.ReadDir(path)
|
||||
}
|
||||
|
||||
func (realFS) ReadDirNames(path string) ([]string, error) {
|
||||
fh, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fh.Close()
|
||||
return fh.Readdirnames(-1)
|
||||
}
|
||||
|
||||
func (realFS) ReadFile(path string) ([]byte, error) {
|
||||
return ioutil.ReadFile(path)
|
||||
}
|
||||
@@ -48,6 +58,11 @@ func ReadDir(path string) ([]os.FileInfo, error) {
|
||||
return fs.ReadDir(path)
|
||||
}
|
||||
|
||||
// ReadDirNames see os.File.ReadDirNames
|
||||
func ReadDirNames(path string) ([]string, error) {
|
||||
return fs.ReadDirNames(path)
|
||||
}
|
||||
|
||||
// ReadFile see ioutil.ReadFile
|
||||
func ReadFile(path string) ([]byte, error) {
|
||||
return fs.ReadFile(path)
|
||||
|
||||
@@ -34,15 +34,10 @@ func walkProcPid(buf *bytes.Buffer, walker process.Walker) (map[uint64]Proc, err
|
||||
walker.Walk(func(p process.Process) {
|
||||
dirName := strconv.Itoa(p.PID)
|
||||
fdBase := filepath.Join(procRoot, dirName, "fd")
|
||||
fds, err := fs.ReadDir(fdBase)
|
||||
if err != nil {
|
||||
// Process is be gone by now, or we don't have access.
|
||||
return
|
||||
}
|
||||
|
||||
// Read network namespace, and if we haven't seen it before,
|
||||
// read /proc/<pid>/net/tcp
|
||||
err = fs.Lstat(filepath.Join(procRoot, dirName, "/ns/net"), &statT)
|
||||
err := fs.Lstat(filepath.Join(procRoot, dirName, "/ns/net"), &statT)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -53,9 +48,14 @@ func walkProcPid(buf *bytes.Buffer, walker process.Walker) (map[uint64]Proc, err
|
||||
readFile(filepath.Join(procRoot, dirName, "/net/tcp6"), buf)
|
||||
}
|
||||
|
||||
fds, err := fs.ReadDirNames(fdBase)
|
||||
if err != nil {
|
||||
// Process is be gone by now, or we don't have access.
|
||||
return
|
||||
}
|
||||
for _, fd := range fds {
|
||||
// Direct use of syscall.Stat() to save garbage.
|
||||
err = fs.Stat(filepath.Join(fdBase, fd.Name()), &statT)
|
||||
err = fs.Stat(filepath.Join(fdBase, fd), &statT)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -23,13 +23,12 @@ func NewWalker(procRoot string) Walker {
|
||||
// passes one-by-one to the supplied function. Walk is only made public
|
||||
// so that is can be tested.
|
||||
func (w *walker) Walk(f func(Process)) error {
|
||||
dirEntries, err := fs.ReadDir(w.procRoot)
|
||||
dirEntries, err := fs.ReadDirNames(w.procRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, dirEntry := range dirEntries {
|
||||
filename := dirEntry.Name()
|
||||
for _, filename := range dirEntries {
|
||||
pid, err := strconv.Atoi(filename)
|
||||
if err != nil {
|
||||
continue
|
||||
|
||||
@@ -89,6 +89,24 @@ func (p dir) ReadDir(path string) ([]os.FileInfo, error) {
|
||||
return fs.ReadDir(tail)
|
||||
}
|
||||
|
||||
func (p dir) ReadDirNames(path string) ([]string, error) {
|
||||
if path == "/" {
|
||||
result := []string{}
|
||||
for _, v := range p.entries {
|
||||
result = append(result, v.Name())
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
head, tail := split(path)
|
||||
fs, ok := p.entries[head]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Not found: %s", path)
|
||||
}
|
||||
|
||||
return fs.ReadDirNames(tail)
|
||||
}
|
||||
|
||||
func (p dir) ReadFile(path string) ([]byte, error) {
|
||||
if path == "/" {
|
||||
return nil, fmt.Errorf("I'm a directory!")
|
||||
@@ -156,6 +174,11 @@ func (p File) ReadDir(path string) ([]os.FileInfo, error) {
|
||||
return nil, fmt.Errorf("I'm a file!")
|
||||
}
|
||||
|
||||
// ReadDirNames implements FS
|
||||
func (p File) ReadDirNames(path string) ([]string, error) {
|
||||
return nil, fmt.Errorf("I'm a file!")
|
||||
}
|
||||
|
||||
// ReadFile implements FS
|
||||
func (p File) ReadFile(path string) ([]byte, error) {
|
||||
if path != "/" {
|
||||
|
||||
Reference in New Issue
Block a user