mirror of https://github.com/golang/go.git
internal/lsp: limit concurrent file reads
We need to limit the concurrent file reads to prevent `too many open file` errors. The first attempt to solve this was done in change 189437, but this change turned out to be incorrect. So this change reverts the changes made in change 189437 and instead adds an new semaphore around the `nativeFileHandle.Read` method. The limit is currently set to half of the lowest open file system limit of *nix, Windows and MacOS system (their respective limits are 1024, 16384, and 256). Change-Id: I27d741e3a3c36eb11bfa7457575f5d5831c06ad7 Reviewed-on: https://go-review.googlesource.com/c/tools/+/190417 Reviewed-by: Ian Cottrell <iancottrell@google.com> Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
9065c182e3
commit
d87e9bbada
|
|
@ -15,6 +15,9 @@ import (
|
|||
"golang.org/x/tools/internal/span"
|
||||
)
|
||||
|
||||
// ioLimit limits the number of parallel file reads per process.
|
||||
var ioLimit = make(chan struct{}, 128)
|
||||
|
||||
// nativeFileSystem implements FileSystem reading from the normal os file system.
|
||||
type nativeFileSystem struct{}
|
||||
|
||||
|
|
@ -54,6 +57,8 @@ func (h *nativeFileHandle) Kind() source.FileKind {
|
|||
func (h *nativeFileHandle) Read(ctx context.Context) ([]byte, string, error) {
|
||||
ctx, done := trace.StartSpan(ctx, "cache.nativeFileHandle.Read", telemetry.File.Of(h.identity.URI.Filename()))
|
||||
defer done()
|
||||
ioLimit <- struct{}{}
|
||||
defer func() { <-ioLimit }()
|
||||
//TODO: this should fail if the version is not the same as the handle
|
||||
data, err := ioutil.ReadFile(h.identity.URI.Filename())
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ import (
|
|||
errors "golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// Limits the number of parallel file reads per process.
|
||||
var ioLimit = make(chan struct{}, 20)
|
||||
// Limits the number of parallel parser calls per process.
|
||||
var parseLimit = make(chan struct{}, 20)
|
||||
|
||||
// parseKey uniquely identifies a parsed Go file.
|
||||
type parseKey struct {
|
||||
|
|
@ -104,13 +104,12 @@ func parseGo(ctx context.Context, c *cache, fh source.FileHandle, mode source.Pa
|
|||
ctx, done := trace.StartSpan(ctx, "cache.parseGo", telemetry.File.Of(fh.Identity().URI.Filename()))
|
||||
defer done()
|
||||
|
||||
ioLimit <- struct{}{}
|
||||
buf, _, err := fh.Read(ctx)
|
||||
<-ioLimit
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parseLimit <- struct{}{}
|
||||
defer func() { <-parseLimit }()
|
||||
parserMode := parser.AllErrors | parser.ParseComments
|
||||
if mode == source.ParseHeader {
|
||||
parserMode = parser.ImportsOnly | parser.ParseComments
|
||||
|
|
|
|||
Loading…
Reference in New Issue