From e5ac43a59e3702d01879b563a550e062bf34f142 Mon Sep 17 00:00:00 2001 From: Sergey Stepanov Date: Thu, 1 Jun 2023 16:16:10 +0300 Subject: [PATCH] Use faster lib scan --- pkg/games/library.go | 44 +++++++++++++-------------------------- pkg/games/library_test.go | 20 +++++++++++++----- 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/pkg/games/library.go b/pkg/games/library.go index c8a84148..fec3cc47 100644 --- a/pkg/games/library.go +++ b/pkg/games/library.go @@ -1,10 +1,7 @@ package games import ( - "crypto/md5" - "fmt" - "io" - "os" + "io/fs" "path/filepath" "strings" "sync" @@ -18,8 +15,8 @@ import ( // libConf is an optimized internal library configuration type libConf struct { path string - supported map[string]bool - ignored map[string]bool + supported map[string]struct{} + ignored map[string]struct{} verbose bool watchMode bool } @@ -37,9 +34,8 @@ type library struct { games map[string]GameMetadata log *logger.Logger - // to restrict parallel execution - // or throttling - // !CAS would be better + // to restrict parallel execution or throttling + // for file watch mode mu sync.Mutex isScanning bool isScanningDelayed bool @@ -56,7 +52,6 @@ type FileExtensionWhitelist interface { } type GameMetadata struct { - uid string // the display name of the game Name string // the game file extension (e.g. nes, n64) @@ -150,16 +145,14 @@ func (lib *library) Scan() { start := time.Now() var games []GameMetadata dir := lib.config.path - err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + err := filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error { if err != nil { return err } - if info != nil && !info.IsDir() && lib.isFileExtensionSupported(path) { + if info != nil && !info.IsDir() && lib.isExtAllowed(path) { meta := getMetadata(path, dir) - meta.uid = hash(path) - - if !lib.config.ignored[meta.Name] { + if _, ok := lib.config.ignored[meta.Name]; !ok { games = append(games, meta) } } @@ -239,12 +232,13 @@ func (lib *library) set(games []GameMetadata) { lib.games = res } -func (lib *library) isFileExtensionSupported(path string) bool { +func (lib *library) isExtAllowed(path string) bool { ext := filepath.Ext(path) if ext == "" { return false } - return lib.config.supported[ext[1:]] + _, ok := lib.config.supported[ext[1:]] + return ok } // getMetadata returns game info from a path @@ -278,20 +272,10 @@ func (lib *library) dumpLibrary() { gameList.String(), len(lib.games), lib.lastScanDuration) } -// hash makes an MD5 hash of the string -func hash(str string) string { - h := md5.New() - _, err := io.WriteString(h, str) - if err != nil { - return "" - } - return fmt.Sprintf("%x", h.Sum(nil)) -} - -func toMap(list []string) map[string]bool { - res := make(map[string]bool) +func toMap(list []string) map[string]struct{} { + res := make(map[string]struct{}, len(list)) for _, s := range list { - res[s] = true + res[s] = struct{}{} } return res } diff --git a/pkg/games/library_test.go b/pkg/games/library_test.go index 759389e8..f42890a8 100644 --- a/pkg/games/library_test.go +++ b/pkg/games/library_test.go @@ -25,16 +25,12 @@ func TestLibraryScan(t *testing.T) { library := NewLib(config.Library{ BasePath: test.directory, Supported: []string{"gba", "zip", "nes"}, - Ignored: []string{"neogeo", "pgm"}, }, l) library.Scan() games := library.GetAll() - list := _map(games, func(meta GameMetadata) string { - return meta.Name - }) + list := _map(games, func(g GameMetadata) string { return g.Name }) - // ^2 complexity (; all := true for _, expect := range test.expected { found := false @@ -52,6 +48,20 @@ func TestLibraryScan(t *testing.T) { } } +func Benchmark(b *testing.B) { + log := logger.Default() + logger.SetGlobalLevel(logger.Disabled) + library := NewLib(config.Library{ + BasePath: "../../assets/games", + Supported: []string{"gba", "zip", "nes"}, + }, log) + + for i := 0; i < b.N; i++ { + library.Scan() + _ = library.GetAll() + } +} + func _map(vs []GameMetadata, f func(info GameMetadata) string) []string { vsm := make([]string, len(vs)) for i, v := range vs {