From e3ca01093c08e6cce875e023ed6379dab66bec69 Mon Sep 17 00:00:00 2001 From: Billy Bolton Date: Mon, 24 Jan 2022 00:17:14 -0500 Subject: [PATCH] make initial directory scan much faster --- .gitignore | 1 + go.mod | 3 ++- go.sum | 2 ++ internal/app.go | 16 +++++++--------- internal/loop.go | 14 ++++++-------- internal/path.go | 32 ++++++++++++++++++++------------ internal/path_test.go | 3 ++- 7 files changed, 40 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index 613a31e..21f1f21 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ bin/ scratch/ /procswap *.coverprofile +/test diff --git a/go.mod b/go.mod index da28054..4faa0f4 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,8 @@ require ( github.com/billiford/go-ps v1.0.3 github.com/eiannone/keyboard v0.0.0-20200508000154-caf4b762e807 github.com/google/uuid v1.2.0 - github.com/logrusorgru/aurora v2.0.3+incompatible + github.com/karrick/godirwalk v1.16.1 // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/mattn/go-colorable v0.1.8 github.com/onsi/ginkgo v1.12.1 github.com/onsi/gomega v1.10.3 diff --git a/go.sum b/go.sum index 081d1a9..8d86eff 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= +github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= diff --git a/internal/app.go b/internal/app.go index 4949cdc..4506c73 100644 --- a/internal/app.go +++ b/internal/app.go @@ -2,11 +2,11 @@ package procswap import ( "fmt" - "os" "path/filepath" "strconv" "strings" + "github.com/karrick/godirwalk" "github.com/logrusorgru/aurora" "github.com/urfave/cli/v2" ) @@ -135,8 +135,7 @@ func run(c *cli.Context) error { logInfo(fmt.Sprintf("%s registered priority script %s", aurora.Cyan("setup"), aurora.Bold(ps))) } // Set limit for loop to run. - limit := c.Int(flagLimitName) - if limit > 0 { + if limit := c.Int(flagLimitName); limit > 0 { loop.WithLimit(limit) } // Set the poll interval. @@ -154,9 +153,9 @@ func run(c *cli.Context) error { return nil } -func listExecutables(paths, ignored []string) []os.FileInfo { +func listExecutables(paths, ignored []string) []*godirwalk.Dirent { // These are our "priority executables". - pe := []os.FileInfo{} + pe := []*godirwalk.Dirent{} // Priority and swap process setup. for _, pd := range paths { @@ -173,10 +172,9 @@ func listExecutables(paths, ignored []string) []os.FileInfo { return pe } -func swaps(pe []os.FileInfo, sp []string) []Swap { +func swaps(pe []*godirwalk.Dirent, sp []string) []Swap { // Make sure there's no intersection here, that would be a nightmare. - err := intersect(pe, sp) - if err != nil { + if err := intersect(pe, sp); err != nil { logFatal(err.Error()) } @@ -188,7 +186,7 @@ func swaps(pe []os.FileInfo, sp []string) []Swap { return swaps } -func intersect(files []os.FileInfo, swaps []string) error { +func intersect(files []*godirwalk.Dirent, swaps []string) error { filesMap := map[string]bool{} for _, file := range files { diff --git a/internal/loop.go b/internal/loop.go index d080873..9967e8a 100644 --- a/internal/loop.go +++ b/internal/loop.go @@ -2,7 +2,6 @@ package procswap import ( "fmt" - "os" "os/exec" "sort" "strings" @@ -10,6 +9,7 @@ import ( "github.com/billiford/go-ps" "github.com/eiannone/keyboard" + "github.com/karrick/godirwalk" "github.com/logrusorgru/aurora" ) @@ -26,7 +26,7 @@ type Loop interface { WithActionsEnabled(bool) WithLimit(int) WithPollInterval(int) - WithPriorities([]os.FileInfo) + WithPriorities([]*godirwalk.Dirent) WithPriorityScript(string) WithPs(ps.Ps) WithSwaps([]Swap) @@ -41,7 +41,7 @@ type loop struct { // poll interval sets how much time in seconds we wait before polling the windows processes. pollInterval int // list of priorities defined at startup. - priorities []os.FileInfo + priorities []*godirwalk.Dirent // a script that will run when any priority starts priorityScript string // ps is the interface for listing processes @@ -69,7 +69,7 @@ func NewLoop() Loop { // Define the loop. loop := &loop{ swaps: []Swap{}, - priorities: []os.FileInfo{}, + priorities: []*godirwalk.Dirent{}, limit: 0, loopCount: 0, ps: ps.New(), @@ -106,7 +106,7 @@ func (l *loop) WithPollInterval(pollInterval int) { } // WithPriorities sets the priority processes for the loop. -func (l *loop) WithPriorities(priorities []os.FileInfo) { +func (l *loop) WithPriorities(priorities []*godirwalk.Dirent) { l.priorities = priorities } @@ -353,9 +353,7 @@ func (l *loop) startPriorityScript() { logInfo(fmt.Sprintf("%s %s...", aurora.Magenta("priority script"), aurora.Bold(l.priorityScript)), false) cmd := exec.Command(l.priorityScript) - - err := cmd.Run() - if err != nil { + if err := cmd.Run(); err != nil { // If there is an error running the priority script, just log it and let the loop continue. logFailed() logError(err.Error()) diff --git a/internal/path.go b/internal/path.go index eda6fb0..115bc2b 100644 --- a/internal/path.go +++ b/internal/path.go @@ -3,16 +3,16 @@ package procswap import ( "fmt" "os" - "path/filepath" "regexp" "strings" + "github.com/karrick/godirwalk" "github.com/logrusorgru/aurora" ) // ProcessList lists all .exe files in a given directory. -func ProcessList(path string, ignored []string) ([]os.FileInfo, error) { - files := []os.FileInfo{} +func ProcessList(path string, ignored []string) ([]*godirwalk.Dirent, error) { + files := []*godirwalk.Dirent{} // Check to make sure it exists first. info, err := os.Stat(path) @@ -26,7 +26,12 @@ func ProcessList(path string, ignored []string) ([]os.FileInfo, error) { // Don't check if it's a .exe if the user has passed in a // single file as priority. if !info.IsDir() { - files = append(files, info) + de, err := godirwalk.NewDirent(path) + if err != nil { + return nil, fmt.Errorf("error creating new dirent for priority file %s: %w", path, err) + } + + files = append(files, de) return files, nil } @@ -36,16 +41,19 @@ func ProcessList(path string, ignored []string) ([]os.FileInfo, error) { // Only list files that end in '.exe'. libRegEx := regexp.MustCompile("^.*.exe$") - err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error { - if err == nil && libRegEx.MatchString(info.Name()) { - if contains(ignored, info.Name()) { - logInfo(fmt.Sprintf("%s ignoring priority %s", aurora.Cyan("setup"), aurora.Bold(info.Name()))) - } else { - files = append(files, info) + err = godirwalk.Walk(path, &godirwalk.Options{ + Callback: func(osPathname string, de *godirwalk.Dirent) error { + if libRegEx.MatchString(de.Name()) { + if contains(ignored, de.Name()) { + logInfo(fmt.Sprintf("%s ignoring priority %s", aurora.Cyan("setup"), aurora.Bold(de.Name()))) + } else { + files = append(files, de) + } } - } - return nil + return nil + }, + Unsorted: true, }) if err != nil { return nil, fmt.Errorf("error walking %s searching for .exes: %w", path, err) diff --git a/internal/path_test.go b/internal/path_test.go index 9cee1d3..533c360 100644 --- a/internal/path_test.go +++ b/internal/path_test.go @@ -5,6 +5,7 @@ import ( "path/filepath" "github.com/google/uuid" + "github.com/karrick/godirwalk" . "github.com/billiford/procswap/internal" . "github.com/onsi/ginkgo" @@ -13,7 +14,7 @@ import ( var _ = Describe("Path", func() { var ( - infos []os.FileInfo + infos []*godirwalk.Dirent ignored []string path string err error