Browse Source

go.d lmsensors improve performance (#18429)

Ilya Mashchenko 6 months ago
parent
commit
4c987bbd06

+ 54 - 56
src/go/plugin/go.d/modules/sensors/lmsensors/scanner.go

@@ -2,7 +2,7 @@ package lmsensors
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io/fs"
 	"os"
 	"path/filepath"
 	"strings"
@@ -13,7 +13,7 @@ type filesystem interface {
 	ReadFile(filename string) (string, error)
 	Readlink(name string) (string, error)
 	Stat(name string) (os.FileInfo, error)
-	Walk(root string, walkFn filepath.WalkFunc) error
+	WalkDir(root string, walkFn fs.WalkDirFunc) error
 }
 
 // A Scanner scans for Devices, so data can be read from their Sensors.
@@ -30,30 +30,31 @@ func New() *Scanner {
 
 // Scan scans for Devices and their Sensors.
 func (s *Scanner) Scan() ([]*Device, error) {
-	// Determine common device locations in Linux /sys filesystem.
 	paths, err := s.detectDevicePaths()
 	if err != nil {
 		return nil, err
 	}
 
 	var devices []*Device
-	for _, p := range paths {
-		d := &Device{}
-		raw := make(map[string]map[string]string, 0)
+
+	for _, rootPath := range paths {
+		dev := &Device{}
+		raw := make(map[string]map[string]string)
 
 		// Walk filesystem paths to fetch devices and sensors
-		err := s.fs.Walk(p, func(path string, info os.FileInfo, err error) error {
+		err := s.fs.WalkDir(rootPath, func(path string, de fs.DirEntry, err error) error {
 			if err != nil {
 				return err
 			}
 
-			// Skip directories and anything that isn't a regular file
-			if info.IsDir() || !info.Mode().IsRegular() {
+			if de.IsDir() || !de.Type().IsRegular() {
+				if de.IsDir() && path != rootPath {
+					return fs.SkipDir
+				}
 				return nil
 			}
 
-			// Skip some files that can't be read or don't provide useful
-			// sensor information
+			// Skip some files that can't be read or don't provide useful sensor information
 			file := filepath.Base(path)
 			if shouldSkip(file) {
 				return nil
@@ -64,48 +65,46 @@ func (s *Scanner) Scan() ([]*Device, error) {
 				return nil
 			}
 
-			switch file {
-			// Found name of device
-			case "name":
-				d.Name = s
+			if file == "name" {
+				dev.Name = s
+				return nil
 			}
 
 			// Sensor names in format "sensor#_foo", e.g. "temp1_input"
-			fs := strings.SplitN(file, "_", 2)
-			if len(fs) != 2 {
+			parts := strings.SplitN(file, "_", 2)
+			if len(parts) != 2 {
 				return nil
 			}
 
-			// Gather sensor data into map for later processing
-			if _, ok := raw[fs[0]]; !ok {
-				raw[fs[0]] = make(map[string]string, 0)
+			if _, ok := raw[parts[0]]; !ok {
+				raw[parts[0]] = make(map[string]string)
 			}
 
-			raw[fs[0]][fs[1]] = s
+			raw[parts[0]][parts[1]] = s
+
 			return nil
 		})
 		if err != nil {
 			return nil, err
 		}
 
-		// Parse all possible sensors from raw data
 		sensors, err := parseSensors(raw)
 		if err != nil {
 			return nil, err
 		}
 
-		d.Sensors = sensors
-		devices = append(devices, d)
+		dev.Sensors = sensors
+		devices = append(devices, dev)
 	}
 
 	renameDevices(devices)
+
 	return devices, nil
 }
 
-// renameDevices renames devices in place to prevent duplicate device names,
-// and to number each device.
+// renameDevices renames devices in place to prevent duplicate device names, and to number each device.
 func renameDevices(devices []*Device) {
-	nameCount := make(map[string]int, 0)
+	nameCount := make(map[string]int)
 
 	for i := range devices {
 		name := devices[i].Name
@@ -117,19 +116,17 @@ func renameDevices(devices []*Device) {
 	}
 }
 
-// detectDevicePaths performs a filesystem walk to paths where devices may
-// reside on Linux.
+// detectDevicePaths performs a filesystem walk to paths where devices may reside on Linux.
 func (s *Scanner) detectDevicePaths() ([]string, error) {
 	const lookPath = "/sys/class/hwmon"
 
 	var paths []string
-	err := s.fs.Walk(lookPath, func(path string, info os.FileInfo, err error) error {
+	err := s.fs.WalkDir(lookPath, func(path string, de os.DirEntry, err error) error {
 		if err != nil {
 			return err
 		}
 
-		// Skip anything that isn't a symlink
-		if info.Mode()&os.ModeSymlink == 0 {
+		if de.Type()&os.ModeSymlink == 0 {
 			return nil
 		}
 
@@ -137,10 +134,10 @@ func (s *Scanner) detectDevicePaths() ([]string, error) {
 		if err != nil {
 			return err
 		}
+
 		dest = filepath.Join(lookPath, filepath.Clean(dest))
 
-		// Symlink destination has a file called name, meaning a sensor exists
-		// here and data can be retrieved
+		// Symlink destination has a file called name, meaning a sensor exists here and data can be retrieved
 		fi, err := s.fs.Stat(filepath.Join(dest, "name"))
 		if err != nil && !os.IsNotExist(err) {
 			return err
@@ -150,16 +147,14 @@ func (s *Scanner) detectDevicePaths() ([]string, error) {
 			return nil
 		}
 
-		// Symlink destination has another symlink called device, which can be
-		// read and used to retrieve data
+		// Symlink destination has another symlink called device, which can be read and used to retrieve data
 		device := filepath.Join(dest, "device")
 		fi, err = s.fs.Stat(device)
 		if err != nil {
-			if os.IsNotExist(err) {
-				return nil
+			if !os.IsNotExist(err) {
+				return err
 			}
-
-			return err
+			return nil
 		}
 
 		if fi.Mode()&os.ModeSymlink != 0 {
@@ -170,27 +165,26 @@ func (s *Scanner) detectDevicePaths() ([]string, error) {
 		if err != nil {
 			return err
 		}
+
 		dest = filepath.Join(dest, filepath.Clean(device))
 
-		// Symlink destination has a file called name, meaning a sensor exists
-		// here and data can be retrieved
+		// Symlink destination has a file called name, meaning a sensor exists here and data can be retrieved
 		if _, err := s.fs.Stat(filepath.Join(dest, "name")); err != nil {
-			if os.IsNotExist(err) {
-				return nil
+			if !os.IsNotExist(err) {
+				return err
 			}
-
-			return err
+			return nil
 		}
 
 		paths = append(paths, dest)
+
 		return nil
 	})
 
 	return paths, err
 }
 
-// shouldSkip indicates if a given filename should be skipped during the
-// filesystem walk operation.
+// shouldSkip indicates if a given filename should be skipped during the filesystem walk operation.
 func shouldSkip(file string) bool {
 	if strings.HasPrefix(file, "runtime_") {
 		return true
@@ -212,21 +206,25 @@ func shouldSkip(file string) bool {
 
 var _ filesystem = &systemFilesystem{}
 
-// A systemFilesystem is a filesystem which uses operations on the host
-// filesystem.
+// A systemFilesystem is a filesystem which uses operations on the host filesystem.
 type systemFilesystem struct{}
 
 func (fs *systemFilesystem) ReadFile(filename string) (string, error) {
-	b, err := ioutil.ReadFile(filename)
+	b, err := os.ReadFile(filename)
 	if err != nil {
 		return "", err
 	}
-
 	return strings.TrimSpace(string(b)), nil
 }
 
-func (fs *systemFilesystem) Readlink(name string) (string, error)  { return os.Readlink(name) }
-func (fs *systemFilesystem) Stat(name string) (os.FileInfo, error) { return os.Stat(name) }
-func (fs *systemFilesystem) Walk(root string, walkFn filepath.WalkFunc) error {
-	return filepath.Walk(root, walkFn)
+func (fs *systemFilesystem) Readlink(name string) (string, error) {
+	return os.Readlink(name)
+}
+
+func (fs *systemFilesystem) Stat(name string) (os.FileInfo, error) {
+	return os.Stat(name)
+}
+
+func (fs *systemFilesystem) WalkDir(root string, walkFn fs.WalkDirFunc) error {
+	return filepath.WalkDir(root, walkFn)
 }

+ 57 - 57
src/go/plugin/go.d/modules/sensors/lmsensors/scanner_test.go

@@ -2,8 +2,8 @@ package lmsensors
 
 import (
 	"fmt"
+	"io/fs"
 	"os"
-	"path/filepath"
 	"reflect"
 	"strings"
 	"testing"
@@ -30,19 +30,19 @@ func TestScannerScan(t *testing.T) {
 				files: []memoryFile{
 					{
 						name: "/sys/class/hwmon",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
 					{
 						name: "/sys/class/hwmon/hwmon0",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							mode: os.ModeSymlink,
 						},
 					},
 					{
 						name: "/sys/devices/LNXSYSTM:00/device:00/ACPI0000:00",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
@@ -51,8 +51,8 @@ func TestScannerScan(t *testing.T) {
 						err:  os.ErrNotExist,
 					},
 					{
-						name: "/sys/devices/LNXSYSTM:00/device:00/ACPI0000:00/hwmon/hwmon0/device",
-						info: &memoryFileInfo{
+						name:     "/sys/devices/LNXSYSTM:00/device:00/ACPI0000:00/hwmon/hwmon0/device",
+						dirEntry: &memoryDirEntry{
 							// mode: os.ModeSymlink,
 						},
 					},
@@ -110,19 +110,19 @@ func TestScannerScan(t *testing.T) {
 				files: []memoryFile{
 					{
 						name: "/sys/class/hwmon",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
 					{
 						name: "/sys/class/hwmon/hwmon0",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							mode: os.ModeSymlink,
 						},
 					},
 					{
 						name: "/sys/devices/virtual/hwmon/hwmon0",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
@@ -162,19 +162,19 @@ func TestScannerScan(t *testing.T) {
 				files: []memoryFile{
 					{
 						name: "/sys/class/hwmon",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
 					{
 						name: "/sys/class/hwmon/hwmon1",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							mode: os.ModeSymlink,
 						},
 					},
 					{
 						name: "/sys/devices/platform/coretemp.0",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
@@ -183,8 +183,8 @@ func TestScannerScan(t *testing.T) {
 						err:  os.ErrNotExist,
 					},
 					{
-						name: "/sys/devices/platform/coretemp.0/hwmon/hwmon1/device",
-						info: &memoryFileInfo{
+						name:     "/sys/devices/platform/coretemp.0/hwmon/hwmon1/device",
+						dirEntry: &memoryDirEntry{
 							// mode: os.ModeSymlink,
 						},
 					},
@@ -266,19 +266,19 @@ func TestScannerScan(t *testing.T) {
 				files: []memoryFile{
 					{
 						name: "/sys/class/hwmon",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
 					{
 						name: "/sys/class/hwmon/hwmon2",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							mode: os.ModeSymlink,
 						},
 					},
 					{
 						name: "/sys/devices/platform/it87.2608",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
@@ -287,8 +287,8 @@ func TestScannerScan(t *testing.T) {
 						err:  os.ErrNotExist,
 					},
 					{
-						name: "/sys/devices/platform/it87.2608/hwmon/hwmon2/device",
-						info: &memoryFileInfo{
+						name:     "/sys/devices/platform/it87.2608/hwmon/hwmon2/device",
+						dirEntry: &memoryDirEntry{
 							// mode: os.ModeSymlink,
 						},
 					},
@@ -426,25 +426,25 @@ func TestScannerScan(t *testing.T) {
 				files: []memoryFile{
 					{
 						name: "/sys/class/hwmon",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
 					{
 						name: "/sys/class/hwmon/hwmon1",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							mode: os.ModeSymlink,
 						},
 					},
 					{
 						name: "/sys/class/hwmon/hwmon2",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							mode: os.ModeSymlink,
 						},
 					},
 					{
 						name: "/sys/devices/platform/coretemp.0",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
@@ -453,8 +453,8 @@ func TestScannerScan(t *testing.T) {
 						err:  os.ErrNotExist,
 					},
 					{
-						name: "/sys/devices/platform/coretemp.0/hwmon/hwmon1/device",
-						info: &memoryFileInfo{
+						name:     "/sys/devices/platform/coretemp.0/hwmon/hwmon1/device",
+						dirEntry: &memoryDirEntry{
 							// mode: os.ModeSymlink,
 						},
 					},
@@ -504,7 +504,7 @@ func TestScannerScan(t *testing.T) {
 					},
 					{
 						name: "/sys/devices/platform/coretemp.1",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
@@ -513,8 +513,8 @@ func TestScannerScan(t *testing.T) {
 						err:  os.ErrNotExist,
 					},
 					{
-						name: "/sys/devices/platform/coretemp.1/hwmon/hwmon2/device",
-						info: &memoryFileInfo{
+						name:     "/sys/devices/platform/coretemp.1/hwmon/hwmon2/device",
+						dirEntry: &memoryDirEntry{
 							// mode: os.ModeSymlink,
 						},
 					},
@@ -619,19 +619,19 @@ func TestScannerScan(t *testing.T) {
 				files: []memoryFile{
 					{
 						name: "/sys/class/hwmon",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
 					{
 						name: "/sys/class/hwmon/hwmon0",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							mode: os.ModeSymlink,
 						},
 					},
 					{
 						name: "/sys/devices/pci0000:00/0000:00:02.0/0000:03:00.0",
-						info: &memoryFileInfo{
+						dirEntry: &memoryDirEntry{
 							isDir: true,
 						},
 					},
@@ -640,8 +640,8 @@ func TestScannerScan(t *testing.T) {
 						err:  os.ErrNotExist,
 					},
 					{
-						name: "/sys/devices/pci0000:00/0000:00:02.0/0000:03:00.0/hwmon/hwmon0/device",
-						info: &memoryFileInfo{
+						name:     "/sys/devices/pci0000:00/0000:00:02.0/0000:03:00.0/hwmon/hwmon0/device",
+						dirEntry: &memoryDirEntry{
 							// mode: os.ModeSymlink,
 						},
 					},
@@ -747,11 +747,11 @@ func (fs *memoryFilesystem) Readlink(name string) (string, error) {
 func (fs *memoryFilesystem) Stat(name string) (os.FileInfo, error) {
 	for _, f := range fs.files {
 		if f.name == name {
-			info := f.info
-			if info == nil {
-				info = &memoryFileInfo{}
+			de := f.dirEntry
+			if de == nil {
+				de = &memoryDirEntry{}
 			}
-
+			info, _ := de.Info()
 			return info, f.err
 		}
 	}
@@ -759,7 +759,7 @@ func (fs *memoryFilesystem) Stat(name string) (os.FileInfo, error) {
 	return nil, fmt.Errorf("stat: file %q not in memory", name)
 }
 
-func (fs *memoryFilesystem) Walk(root string, walkFn filepath.WalkFunc) error {
+func (fs *memoryFilesystem) WalkDir(root string, walkFn fs.WalkDirFunc) error {
 	if _, err := fs.Stat(root); err != nil {
 		return err
 	}
@@ -770,12 +770,12 @@ func (fs *memoryFilesystem) Walk(root string, walkFn filepath.WalkFunc) error {
 			continue
 		}
 
-		info := f.info
-		if info == nil {
-			info = &memoryFileInfo{}
+		de := f.dirEntry
+		if de == nil {
+			de = &memoryDirEntry{}
 		}
 
-		if err := walkFn(f.name, info, nil); err != nil {
+		if err := walkFn(f.name, de, nil); err != nil {
 			return err
 		}
 	}
@@ -787,24 +787,24 @@ func (fs *memoryFilesystem) Walk(root string, walkFn filepath.WalkFunc) error {
 type memoryFile struct {
 	name     string
 	contents string
-	info     os.FileInfo
+	dirEntry fs.DirEntry
 	err      error
 }
 
-var _ os.FileInfo = &memoryFileInfo{}
+var _ fs.DirEntry = &memoryDirEntry{}
 
-// A memoryFileInfo is an os.FileInfo used by memoryFiles.
-type memoryFileInfo struct {
-	name    string
-	size    int64
-	mode    os.FileMode
-	modTime time.Time
-	isDir   bool
+// A memoryDirEntry is a fs.DirEntry used by memoryFiles.
+type memoryDirEntry struct {
+	name  string
+	mode  os.FileMode
+	isDir bool
 }
 
-func (fi *memoryFileInfo) Name() string       { return fi.name }
-func (fi *memoryFileInfo) Size() int64        { return fi.size }
-func (fi *memoryFileInfo) Mode() os.FileMode  { return fi.mode }
-func (fi *memoryFileInfo) ModTime() time.Time { return fi.modTime }
-func (fi *memoryFileInfo) IsDir() bool        { return fi.isDir }
-func (fi *memoryFileInfo) Sys() interface{}   { return nil }
+func (fi *memoryDirEntry) Name() string               { return fi.name }
+func (fi *memoryDirEntry) Type() os.FileMode          { return fi.mode }
+func (fi *memoryDirEntry) IsDir() bool                { return fi.isDir }
+func (fi *memoryDirEntry) Info() (fs.FileInfo, error) { return fi, nil }
+func (fi *memoryDirEntry) Sys() interface{}           { return nil }
+func (fi *memoryDirEntry) Size() int64                { return 0 }
+func (fi *memoryDirEntry) Mode() os.FileMode          { return fi.Type() }
+func (fi *memoryDirEntry) ModTime() time.Time         { return time.Now() }