Skip to content

Commit 492d69e

Browse files
authored
perf: improve IsStandardPackage (#165)
* perf: improve IsStandardPackage * perf: improve IsStandardLibrary * perf: git commit * perf: cgo packages.Load
1 parent f90ee7e commit 492d69e

File tree

3 files changed

+55
-15
lines changed

3 files changed

+55
-15
lines changed

lang/golang/parser/pkg.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,31 +185,36 @@ func (p *GoParser) loadPackages(mod *Module, dir string, pkgPath PkgPath) (err e
185185
Mode: baseOpts,
186186
Fset: fset,
187187
Dir: dir,
188+
Env: append(os.Environ(), "GOSUMDB=off"),
188189
}
189190

190191
if p.opts.NeedTest {
191192
cfg.Tests = true
192193
}
193194

194-
pkgs, err := packages.Load(cfg, pkgPath)
195-
if err != nil {
196-
return fmt.Errorf("load path '%s' failed: %v", dir, err)
197-
}
198-
199195
hasCGO := false
200196
if len(p.cgoPkgs) > 0 {
201197
hasCGO = true
202198
}
203-
fmt.Fprintf(os.Stderr, "[loadPackages] mod: %s, dir: %s, pkgPath: %s, hasCGO: %v\n", mod.Name, dir, pkgPath, hasCGO)
199+
200+
var pkgs []*packages.Package
201+
204202
if hasCGO {
205203
baseOpts |= packages.NeedCompiledGoFiles
206204
cfg.Mode = baseOpts
207205
pkgs, err = packages.Load(cfg, pkgPath)
208206
if err != nil {
209207
return fmt.Errorf("load path '%s' with CGO failed: %v", dir, err)
210208
}
209+
} else {
210+
pkgs, err = packages.Load(cfg, pkgPath)
211+
if err != nil {
212+
return fmt.Errorf("load path '%s' failed: %v", dir, err)
213+
}
211214
}
212215

216+
fmt.Fprintf(os.Stderr, "[loadPackages] mod: %s, dir: %s, pkgPath: %s, hasCGO: %v\n", mod.Name, dir, pkgPath, hasCGO)
217+
213218
for _, pkg := range pkgs {
214219
if mm := p.repo.Modules[mod.Name]; mm != nil && (*mm).Packages[pkg.ID] != nil {
215220
continue

lang/golang/parser/utils.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ import (
1818
"container/list"
1919
"fmt"
2020
"go/ast"
21-
"go/build"
2221
"go/types"
2322
"os"
2423
"os/exec"
2524
"path"
2625
"path/filepath"
2726
"regexp"
27+
"runtime"
2828
"strings"
2929
"sync"
3030

@@ -112,20 +112,27 @@ func (pc *PackageCache) IsStandardPackage(path string) bool {
112112
return isStd
113113
}
114114

115-
pkg, err := build.Import(path, "", build.FindOnly)
116-
if err != nil {
117-
// Cannot find the package, assume it's not a standard package
118-
pc.set(path, false)
115+
isStd := IsStandardLibrary(path)
116+
pc.set(path, isStd)
117+
return isStd
118+
}
119+
120+
func IsStandardLibrary(pkgPath string) bool {
121+
122+
goroot := runtime.GOROOT()
123+
if goroot == "" {
119124
return false
120125
}
121126

122-
isStd := pkg.Goroot
123-
pc.set(path, isStd)
127+
dir := filepath.Join(goroot, "src", pkgPath)
128+
info, err := os.Stat(dir)
129+
isStd := err == nil && info.IsDir()
130+
124131
return isStd
125132
}
126133

127134
// stdlibCache 缓存 importPath 是否是 system package, 10000 个缓存
128-
var stdlibCache = NewPackageCache(10000)
135+
var stdlibCache = NewPackageCache(100000)
129136

130137
func isSysPkg(importPath string) bool {
131138
return stdlibCache.IsStandardPackage(importPath)
@@ -311,14 +318,21 @@ func isUpperCase(c byte) bool {
311318
return c >= 'A' && c <= 'Z'
312319
}
313320

321+
var commitHashCache sync.Map
322+
314323
func getCommitHash(dir string) (string, error) {
324+
if val, ok := commitHashCache.Load(dir); ok {
325+
return val.(string), nil
326+
}
315327
cmd := exec.Command("git", "rev-parse", "HEAD")
316328
cmd.Dir = dir
317329
output, err := cmd.Output()
318330
if err != nil {
319331
return "", fmt.Errorf("failed to get commit hash: %v", err)
320332
}
321-
return strings.TrimSpace(string(output)), nil
333+
hash := strings.TrimSpace(string(output))
334+
commitHashCache.Store(dir, hash)
335+
return hash, nil
322336
}
323337

324338
type workFile struct {

lang/golang/parser/utils_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"go/parser"
2121
"go/token"
2222
"go/types"
23+
"os"
2324
"slices"
2425
"sync"
2526
"testing"
@@ -285,3 +286,23 @@ func Test_isSysPkg(t *testing.T) {
285286
assert.False(t, foundOs, "os should have been evicted from the cache")
286287
})
287288
}
289+
290+
func Test_getCommitHash(t *testing.T) {
291+
wd, err := os.Getwd()
292+
require.NoError(t, err)
293+
294+
// First call, should execute git command
295+
hash1, err := getCommitHash(wd)
296+
require.NoError(t, err)
297+
require.NotEmpty(t, hash1)
298+
299+
// Second call, should come from cache
300+
hash2, err := getCommitHash(wd)
301+
require.NoError(t, err)
302+
require.Equal(t, hash1, hash2)
303+
304+
// Check cache directly
305+
cached, ok := commitHashCache.Load(wd)
306+
require.True(t, ok)
307+
require.Equal(t, hash1, cached)
308+
}

0 commit comments

Comments
 (0)