Skip to content

Commit

Permalink
gopls/internal/lsp/cache: limit module scan to 100K files
Browse files Browse the repository at this point in the history
When no go.work or go.mod file is found, gopls searches to see if there
is exactly one module in a nested directory, in which case it narrows
the workspace to this one module. This is a legacy workaround for
polyglot repositories, and will be made obsolete by golang/go#57979.

However, in the meantime this feature is still necessary, and is the
last remaining place where we walk the workspace looking for modules. As
reported in golang/go#56496, this search can be expensive in very large
directories.

Reduce the search limit 10x, from 1M->100K, and use the more efficient
filepath.WalkDir.

Fixes golang/go#56496

Change-Id: Ia46dd90ac2220b09debc68742dd882885c38eb42
Reviewed-on: https://go-review.googlesource.com/c/tools/+/496880
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
  • Loading branch information
findleyr committed May 22, 2023
1 parent 9ca66ba commit e6fd7f4
Showing 1 changed file with 6 additions and 2 deletions.
8 changes: 6 additions & 2 deletions gopls/internal/lsp/cache/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"sort"
Expand Down Expand Up @@ -127,7 +128,10 @@ var errExhausted = errors.New("exhausted")

// Limit go.mod search to 1 million files. As a point of reference,
// Kubernetes has 22K files (as of 2020-11-24).
const fileLimit = 1000000
//
// Note: per golang/go#56496, the previous limit of 1M files was too slow, at
// which point this limit was decreased to 100K.
const fileLimit = 100_000

// findModules recursively walks the root directory looking for go.mod files,
// returning the set of modules it discovers. If modLimit is non-zero,
Expand All @@ -139,7 +143,7 @@ func findModules(root span.URI, excludePath func(string) bool, modLimit int) (ma
modFiles := make(map[span.URI]struct{})
searched := 0
errDone := errors.New("done")
err := filepath.Walk(root.Filename(), func(path string, info os.FileInfo, err error) error {
err := filepath.WalkDir(root.Filename(), func(path string, info fs.DirEntry, err error) error {
if err != nil {
// Probably a permission error. Keep looking.
return filepath.SkipDir
Expand Down

0 comments on commit e6fd7f4

Please sign in to comment.