From: Charlie Vieth Date: Sat, 12 Mar 2022 22:27:42 +0000 (-0500) Subject: go/build: replace ioutil.ReadDir with os.ReadDir X-Git-Tag: go1.19beta1~306 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=536282763f7357edd81d85993c12fd977fecd378;p=gostls13.git go/build: replace ioutil.ReadDir with os.ReadDir Change go/build.readDir to use os.ReadDir instead of ioutil.ReadDir. This addresses a TODO and improves performance on Darwin and Linux. Darwin: Apple M1 name old time/op new time/op delta ImportVendor-10 39.8µs ± 1% 37.0µs ± 1% -6.91% (p=0.000 n=10+10) Linux: Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz name old time/op new time/op delta ImportVendor-16 22.9µs ±11% 21.2µs ± 5% -7.47% (p=0.001 n=10+9) Updates #45557 Change-Id: Ib1bd2e66210e714e499a035847d6261b61b7e2c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/392074 Run-TryBot: Ian Lance Taylor Reviewed-by: Daniel Martí Reviewed-by: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov TryBot-Result: Gopher Robot Auto-Submit: Ian Lance Taylor --- diff --git a/src/go/build/build.go b/src/go/build/build.go index 836e279d92..039b422dab 100644 --- a/src/go/build/build.go +++ b/src/go/build/build.go @@ -17,7 +17,6 @@ import ( "internal/goversion" "io" "io/fs" - "io/ioutil" "os" "os/exec" pathpkg "path" @@ -186,13 +185,21 @@ func hasSubdir(root, dir string) (rel string, ok bool) { return filepath.ToSlash(dir[len(root):]), true } -// readDir calls ctxt.ReadDir (if not nil) or else ioutil.ReadDir. -func (ctxt *Context) readDir(path string) ([]fs.FileInfo, error) { +// readDir calls ctxt.ReadDir (if not nil) or else os.ReadDir. +func (ctxt *Context) readDir(path string) ([]fs.DirEntry, error) { + // TODO: add a fs.DirEntry version of Context.ReadDir if f := ctxt.ReadDir; f != nil { - return f(path) + fis, err := f(path) + if err != nil { + return nil, err + } + des := make([]fs.DirEntry, len(fis)) + for i, fi := range fis { + des[i] = fs.FileInfoToDirEntry(fi) + } + return des, nil } - // TODO: use os.ReadDir - return ioutil.ReadDir(path) + return os.ReadDir(path) } // openFile calls ctxt.OpenFile (if not nil) or else os.Open. @@ -836,7 +843,7 @@ Found: if d.IsDir() { continue } - if d.Mode()&fs.ModeSymlink != 0 { + if d.Type() == fs.ModeSymlink { if ctxt.isDir(ctxt.joinPath(p.Dir, d.Name())) { // Symlinks to directories are not source files. continue diff --git a/src/go/build/build_test.go b/src/go/build/build_test.go index 36bcae179e..8fa17c7343 100644 --- a/src/go/build/build_test.go +++ b/src/go/build/build_test.go @@ -567,6 +567,27 @@ func TestImportVendor(t *testing.T) { } } +func BenchmarkImportVendor(b *testing.B) { + testenv.MustHaveGoBuild(b) // really must just have source + + b.Setenv("GO111MODULE", "off") + + ctxt := Default + wd, err := os.Getwd() + if err != nil { + b.Fatal(err) + } + ctxt.GOPATH = filepath.Join(wd, "testdata/withvendor") + dir := filepath.Join(ctxt.GOPATH, "src/a/b") + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := ctxt.Import("c/d", dir, 0) + if err != nil { + b.Fatalf("cannot find vendored c/d from testdata src/a/b directory: %v", err) + } + } +} + func TestImportVendorFailure(t *testing.T) { testenv.MustHaveGoBuild(t) // really must just have source