Skip to content

Commit fc8d614

Browse files
committed
speedup skip-dirs processing by caching
1 parent 4fd88b9 commit fc8d614

File tree

2 files changed

+65
-16
lines changed

2 files changed

+65
-16
lines changed

pkg/lint/runner.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func NewRunner(astCache *astcache.Cache, cfg *config.Config, log logutils.Log, g
7575
skipDirsProcessor, // must be after path prettifier
7676

7777
processors.NewAutogeneratedExclude(astCache),
78-
processors.NewIdentifierMarker(), // must be befor exclude
78+
processors.NewIdentifierMarker(), // must be before exclude because users see already marked output and configure excluding by it
7979
processors.NewExclude(excludeTotalPattern),
8080
processors.NewExcludeRules(excludeRules, lineCache, log.Child("exclude_rules")),
8181
processors.NewNolint(astCache, log.Child("nolint"), dbManager),
@@ -92,6 +92,8 @@ func NewRunner(astCache *astcache.Cache, cfg *config.Config, log logutils.Log, g
9292
}, nil
9393
}
9494

95+
func someUnusedFunc() {}
96+
9597
type lintRes struct {
9698
linter *linter.Config
9799
err error
@@ -217,13 +219,19 @@ func (r *Runner) runWorkers(ctx context.Context, lintCtx *linter.Context, linter
217219
return lintResultsCh
218220
}
219221

222+
type processorStat struct {
223+
inCount int
224+
outCount int
225+
}
226+
220227
func (r Runner) processLintResults(inCh <-chan lintRes) <-chan lintRes {
221228
outCh := make(chan lintRes, 64)
222229

223230
go func() {
224231
sw := timeutils.NewStopwatch("processing", r.Log)
225232

226233
var issuesBefore, issuesAfter int
234+
statPerProcessor := map[string]processorStat{}
227235
defer close(outCh)
228236

229237
for res := range inCh {
@@ -234,7 +242,7 @@ func (r Runner) processLintResults(inCh <-chan lintRes) <-chan lintRes {
234242

235243
if len(res.issues) != 0 {
236244
issuesBefore += len(res.issues)
237-
res.issues = r.processIssues(res.issues, sw)
245+
res.issues = r.processIssues(res.issues, sw, statPerProcessor)
238246
issuesAfter += len(res.issues)
239247
outCh <- res
240248
}
@@ -252,12 +260,23 @@ func (r Runner) processLintResults(inCh <-chan lintRes) <-chan lintRes {
252260
if issuesBefore != issuesAfter {
253261
r.Log.Infof("Issues before processing: %d, after processing: %d", issuesBefore, issuesAfter)
254262
}
263+
r.printPerProcessorStat(statPerProcessor)
255264
sw.PrintStages()
256265
}()
257266

258267
return outCh
259268
}
260269

270+
func (r Runner) printPerProcessorStat(stat map[string]processorStat) {
271+
parts := make([]string, 0, len(stat))
272+
for name, ps := range stat {
273+
if ps.inCount != 0 {
274+
parts = append(parts, fmt.Sprintf("%s: %d/%d", name, ps.outCount, ps.inCount))
275+
}
276+
}
277+
r.Log.Infof("Processors filtering stat (out/in): %s", strings.Join(parts, ", "))
278+
}
279+
261280
func collectIssues(resCh <-chan lintRes) <-chan result.Issue {
262281
retIssues := make(chan result.Issue, 1024)
263282
go func() {
@@ -294,7 +313,7 @@ func (r Runner) Run(ctx context.Context, linters []*linter.Config, lintCtx *lint
294313
return collectIssues(processedLintResultsCh)
295314
}
296315

297-
func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch) []result.Issue {
316+
func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch, statPerProcessor map[string]processorStat) []result.Issue {
298317
for _, p := range r.Processors {
299318
var newIssues []result.Issue
300319
var err error
@@ -306,6 +325,10 @@ func (r *Runner) processIssues(issues []result.Issue, sw *timeutils.Stopwatch) [
306325
if err != nil {
307326
r.Log.Warnf("Can't process result by %s processor: %s", p.Name(), err)
308327
} else {
328+
stat := statPerProcessor[p.Name()]
329+
stat.inCount += len(issues)
330+
stat.outCount += len(newIssues)
331+
statPerProcessor[p.Name()] = stat
309332
issues = newIssues
310333
}
311334

pkg/result/processors/skip_dirs.go

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@ import (
1111
"github.com/golangci/golangci-lint/pkg/result"
1212
)
1313

14+
type skipStat struct {
15+
pattern string
16+
count int
17+
}
18+
1419
type SkipDirs struct {
15-
patterns []*regexp.Regexp
16-
log logutils.Log
17-
skippedDirs map[string]string // dir to the last regexp mapping
18-
absArgsDirs []string
20+
patterns []*regexp.Regexp
21+
log logutils.Log
22+
skippedDirs map[string]*skipStat
23+
absArgsDirs []string
24+
skippedDirsCache map[string]bool
1925
}
2026

2127
var _ Processor = SkipFiles{}
@@ -50,14 +56,15 @@ func NewSkipDirs(patterns []string, log logutils.Log, runArgs []string) (*SkipDi
5056
}
5157

5258
return &SkipDirs{
53-
patterns: patternsRe,
54-
log: log,
55-
skippedDirs: map[string]string{},
56-
absArgsDirs: absArgsDirs,
59+
patterns: patternsRe,
60+
log: log,
61+
skippedDirs: map[string]*skipStat{},
62+
absArgsDirs: absArgsDirs,
63+
skippedDirsCache: map[string]bool{},
5764
}, nil
5865
}
5966

60-
func (p SkipDirs) Name() string {
67+
func (p *SkipDirs) Name() string {
6168
return "skip_dirs"
6269
}
6370

@@ -78,12 +85,26 @@ func (p *SkipDirs) shouldPassIssue(i *result.Issue) bool {
7885
}
7986

8087
issueRelDir := filepath.Dir(i.FilePath())
88+
89+
if toPass, ok := p.skippedDirsCache[issueRelDir]; ok {
90+
if !toPass {
91+
p.skippedDirs[issueRelDir].count++
92+
}
93+
return toPass
94+
}
95+
8196
issueAbsDir, err := filepath.Abs(issueRelDir)
8297
if err != nil {
8398
p.log.Warnf("Can't abs-ify path %q: %s", issueRelDir, err)
8499
return true
85100
}
86101

102+
toPass := p.shouldPassIssueDirs(issueRelDir, issueAbsDir)
103+
p.skippedDirsCache[issueRelDir] = toPass
104+
return toPass
105+
}
106+
107+
func (p *SkipDirs) shouldPassIssueDirs(issueRelDir, issueAbsDir string) bool {
87108
for _, absArgDir := range p.absArgsDirs {
88109
if absArgDir == issueAbsDir {
89110
// we must not skip issues if they are from explicitly set dirs
@@ -101,16 +122,21 @@ func (p *SkipDirs) shouldPassIssue(i *result.Issue) bool {
101122
for _, pattern := range p.patterns {
102123
if pattern.MatchString(issueRelDir) {
103124
ps := pattern.String()
104-
p.skippedDirs[issueRelDir] = ps
125+
if p.skippedDirs[issueRelDir] == nil {
126+
p.skippedDirs[issueRelDir] = &skipStat{
127+
pattern: ps,
128+
}
129+
}
130+
p.skippedDirs[issueRelDir].count++
105131
return false
106132
}
107133
}
108134

109135
return true
110136
}
111137

112-
func (p SkipDirs) Finish() {
113-
for dir, pattern := range p.skippedDirs {
114-
p.log.Infof("Skipped dir %s by pattern %s", dir, pattern)
138+
func (p *SkipDirs) Finish() {
139+
for dir, stat := range p.skippedDirs {
140+
p.log.Infof("Skipped %d issues from dir %s by pattern %s", stat.count, dir, stat.pattern)
115141
}
116142
}

0 commit comments

Comments
 (0)