Skip to content
This repository was archived by the owner on Jan 31, 2024. It is now read-only.

Commit 2702523

Browse files
author
Henry Wong
authored
[elastic] Cache the results of 'invokeGo()' call (#76)
'invokeGo' is used to get the import outline of the specified folder(package), so there are duplications that will slow down the go langserver. Since go langserver serves several repos at the same time, use LRU cache in case of blow up the memory. 'determineRootDirsCached' serves single view, i.e. single workspace folder, 'golistDriverLRUCached' serves single subfolder, i.e. package. Given that we will skip 'vendor' folder, for now, the number of the repos are simultaneously indexing is very low, that's why set the 'determineRootDirsCached' entry number to 16. Future plan: skip the 'vendor' file download the deps during the initialize request eliminate the 'invokeGo' call find a better approach to handle the 'vendor' folder
1 parent 5a1b831 commit 2702523

File tree

7 files changed

+68
-3
lines changed

7 files changed

+68
-3
lines changed

.ci/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ ENV GO111MODULE=off
77
RUN apk add --no-cache --quiet make curl git jq unzip tree && \
88
apk add bash && \
99
go get golang.org/x/sync/errgroup && \
10-
go get golang.org/x/xerrors
10+
go get golang.org/x/xerrors && \
11+
go get github.com/hashicorp/golang-lru
1112

1213
VOLUME /go/src/golang.org/x/tools
1314
WORKDIR /go/src/golang.org/x/tools

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ env:
2424
before_install:
2525
- go get golang.org/x/sync/errgroup
2626
- go get golang.org/x/xerrors
27+
- go get github.com/hashicorp/golang-lru
2728

2829
matrix:
2930
fast_finish: true

appveyor.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ environment:
2626
build_script:
2727
- go get golang.org/x/sync/errgroup
2828
- go get golang.org/x/xerrors
29+
- go get github.com/hashicorp/golang-lru
2930
# TODO(henrywong) For now, there are problems about the windows test.
3031
# - go test ./internal/lsp -v
3132
- mkdir go-langserver-windows

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module golang.org/x/tools
33
go 1.11
44

55
require (
6+
github.com/hashicorp/golang-lru v0.5.3
67
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
78
golang.org/x/sync v0.0.0-20190423024810-112230192c58
89
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk=
2+
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
13
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
24
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
35
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=

go/packages/golist.go

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"encoding/json"
1010
"fmt"
1111
"go/types"
12+
"hash/fnv"
1213
"io/ioutil"
1314
"log"
1415
"os"
@@ -22,6 +23,7 @@ import (
2223
"sync"
2324
"time"
2425

26+
"github.com/hashicorp/golang-lru"
2527
"golang.org/x/tools/go/internal/packagesdriver"
2628
"golang.org/x/tools/internal/gopathwalk"
2729
"golang.org/x/tools/internal/semver"
@@ -91,7 +93,7 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
9193
var rootDirs map[string]string
9294
var rootDirsReady = make(chan struct{})
9395
go func() {
94-
rootDirs = determineRootDirs(cfg)
96+
rootDirs = determineRootDirsLRUCached(cfg)
9597
close(rootDirsReady)
9698
}()
9799
getRootDirs := func() map[string]string {
@@ -101,7 +103,7 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
101103

102104
// always pass getRootDirs to golistDriver
103105
golistDriver := func(cfg *Config, patterns ...string) (*driverResponse, error) {
104-
return golistDriver(cfg, getRootDirs, patterns...)
106+
return golistDriverLRUCached(cfg, getRootDirs, patterns...)
105107
}
106108

107109
// Determine files requested in contains patterns
@@ -597,6 +599,36 @@ func otherFiles(p *jsonPackage) [][]string {
597599
return [][]string{p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.SwigFiles, p.SwigCXXFiles, p.SysoFiles}
598600
}
599601

602+
type goListResult struct {
603+
response *driverResponse
604+
err error
605+
}
606+
607+
var (
608+
goListLRUCache *lru.Cache
609+
createGoListLRUCache sync.Once
610+
goListLRUEntries = 16 * 32
611+
)
612+
613+
func golistDriverLRUCached(cfg *Config, rootsDirs func() map[string]string, words ...string) (*driverResponse, error) {
614+
createGoListLRUCache.Do(func() {
615+
goListLRUCache, _ = lru.New(goListLRUEntries)
616+
})
617+
618+
h := fnv.New32a()
619+
h.Write([]byte(cfg.Dir))
620+
h.Write([]byte(words[len(words)-1]))
621+
hashKey := h.Sum32()
622+
if val, ok := goListLRUCache.Get(hashKey); ok {
623+
res := val.(goListResult)
624+
return res.response, res.err
625+
} else {
626+
res, err := golistDriver(cfg, rootsDirs, words...)
627+
goListLRUCache.Add(hashKey, goListResult{res, err})
628+
return res, err
629+
}
630+
}
631+
600632
// golistDriver uses the "go list" command to expand the pattern
601633
// words and return metadata for the specified packages. dir may be
602634
// "" and env may be nil, as per os/exec.Command.

go/packages/golist_overlay.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import (
1010
"path/filepath"
1111
"strconv"
1212
"strings"
13+
"sync"
14+
15+
"github.com/hashicorp/golang-lru"
1316
)
1417

1518
// processGolistOverlay provides rudimentary support for adding
@@ -194,6 +197,30 @@ func hasTestFiles(p *Package) bool {
194197
return false
195198
}
196199

200+
type determineRootDirsResult struct {
201+
roots map[string]string
202+
}
203+
204+
var (
205+
determineRootDirsLRUCache *lru.Cache
206+
createRootLRUCache sync.Once
207+
rootLRUEntries = 16
208+
)
209+
210+
func determineRootDirsLRUCached(cfg *Config) map[string]string {
211+
createRootLRUCache.Do(func() {
212+
determineRootDirsLRUCache, _ = lru.New(rootLRUEntries)
213+
})
214+
if val, ok := determineRootDirsLRUCache.Get(cfg.Dir); ok {
215+
res := val.(determineRootDirsResult)
216+
return res.roots
217+
} else {
218+
roots := determineRootDirs(cfg)
219+
determineRootDirsLRUCache.Add(cfg.Dir, determineRootDirsResult{roots})
220+
return roots
221+
}
222+
}
223+
197224
// determineRootDirs returns a mapping from directories code can be contained in to the
198225
// corresponding import path prefixes of those directories.
199226
// Its result is used to try to determine the import path for a package containing

0 commit comments

Comments
 (0)