From b641321c2a178bfa4a0515f80136555d2ee13397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Wed, 29 May 2024 10:21:07 +0100 Subject: [PATCH] cue/load: cache which directories are missing in importPkg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids repeated calls to os.Stat via fileSystem.isDir. It reduces the number of syscalls from $ strace -f -t -e trace=file cue fmt ./internal/ci |& grep '/home/mvdan/src' | wc -l 90 $ strace -f -t -e trace=file cue fmt ./... |& grep '/home/mvdan/src' | wc -l 5224 by about 3% and 20% respectively to $ strace -f -t -e trace=file cue fmt ./internal/ci |& grep '/home/mvdan/src' | wc -l 87 $ strace -f -t -e trace=file cue fmt ./... |& grep '/home/mvdan/src' | wc -l 4162 Updates #3155. Signed-off-by: Daniel Martí Change-Id: I51e09a0adf233788c5c92c62c20a743b7873e73e --- cue/load/fs.go | 9 --------- cue/load/import.go | 9 +++++++-- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/cue/load/fs.go b/cue/load/fs.go index 58681355dfd..8ec96dce3da 100644 --- a/cue/load/fs.go +++ b/cue/load/fs.go @@ -141,15 +141,6 @@ func (fs *fileSystem) makeAbs(path string) string { return filepath.Join(fs.cwd, path) } -func (fs *fileSystem) isDir(path string) bool { - path = fs.makeAbs(path) - if fs.getDir(path, false) != nil { - return true - } - fi, err := os.Stat(path) - return err == nil && fi.IsDir() -} - func (fs *fileSystem) readDir(path string) ([]iofs.DirEntry, errors.Error) { path = fs.makeAbs(path) m := fs.getDir(path, false) diff --git a/cue/load/import.go b/cue/load/import.go index 3f3895f2b83..536bbd1a8bc 100644 --- a/cue/load/import.go +++ b/cue/load/import.go @@ -18,6 +18,7 @@ import ( "cmp" "fmt" "io" + "io/fs" "os" pathpkg "path" "path/filepath" @@ -141,13 +142,17 @@ func (l *loader) importPkg(pos token.Pos, p *build.Instance) []*build.Instance { // since a package foo/bar/baz inherits from parent packages foo/bar and foo. // See https://cuelang.org/docs/concept/modules-packages-instances/#instances. for _, d := range dirs { - for dir := filepath.Clean(d[1]); ctxt.isDir(dir); { + dir := filepath.Clean(d[1]) + for { sd, ok := l.dirCachedBuildFiles[dir] if !ok { sd = l.scanDir(dir) l.dirCachedBuildFiles[dir] = sd } if err := sd.err; err != nil { + if errors.Is(err, fs.ErrNotExist) { + break + } return retErr(errors.Wrapf(err, token.NoPos, "import failed reading dir %v", dir)) } p.UnknownFiles = append(p.UnknownFiles, sd.unknownFiles...) @@ -208,7 +213,7 @@ func (l *loader) importPkg(pos token.Pos, p *build.Instance) []*build.Instance { func (l *loader) scanDir(dir string) cachedFileFiles { sd := cachedFileFiles{} files, err := l.cfg.fileSystem.readDir(dir) - if err != nil && !os.IsNotExist(err) { + if err != nil { sd.err = err return sd }