Skip to content
This repository has been archived by the owner on Sep 9, 2020. It is now read-only.

Commit

Permalink
Merge pull request #1215 from jmank88/mem-cache-opt
Browse files Browse the repository at this point in the history
gps: source cache: memory cache optimization
  • Loading branch information
sdboyer committed Sep 30, 2017
2 parents 3fd5bb3 + 31ede57 commit ac1a162
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 39 deletions.
6 changes: 4 additions & 2 deletions internal/gps/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,10 @@ func (sg *sourceGateway) listVersions(ctx context.Context) ([]PairedVersion, err
if err != nil {
return nil, err
}

return sg.cache.getAllVersions(), nil
if pvs, ok := sg.cache.getAllVersions(); ok {
return pvs, nil
}
return nil, nil
}

func (sg *sourceGateway) revisionPresentIn(ctx context.Context, r Revision) (bool, error) {
Expand Down
26 changes: 15 additions & 11 deletions internal/gps/source_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type singleSourceCache interface {
getVersionsFor(Revision) ([]UnpairedVersion, bool)

// Gets all the version pairs currently known to the cache.
getAllVersions() []PairedVersion
getAllVersions() ([]PairedVersion, bool)

// Get the revision corresponding to the given unpaired version.
getRevisionFor(UnpairedVersion) (Revision, bool)
Expand All @@ -61,9 +61,10 @@ type singleSourceCache interface {
}

type singleSourceCacheMemory struct {
mut sync.RWMutex // protects all maps
mut sync.RWMutex // protects all fields
infos map[ProjectAnalyzerInfo]map[Revision]projectInfo
ptrees map[Revision]pkgtree.PackageTree
vList []PairedVersion // replaced, never modified
vMap map[UnpairedVersion]Revision
rMap map[Revision][]UnpairedVersion
}
Expand Down Expand Up @@ -136,13 +137,14 @@ func (c *singleSourceCacheMemory) getPackageTree(r Revision) (pkgtree.PackageTre

func (c *singleSourceCacheMemory) setVersionMap(versionList []PairedVersion) {
c.mut.Lock()
c.vList = versionList
// TODO(sdboyer) how do we handle cache consistency here - revs that may
// be out of date vis-a-vis the ptrees or infos maps?
for r := range c.rMap {
c.rMap[r] = nil
}

c.vMap = make(map[UnpairedVersion]Revision)
c.vMap = make(map[UnpairedVersion]Revision, len(versionList))

for _, pv := range versionList {
u, r := pv.Unpair(), pv.Revision()
Expand All @@ -167,15 +169,17 @@ func (c *singleSourceCacheMemory) getVersionsFor(r Revision) ([]UnpairedVersion,
return versionList, has
}

func (c *singleSourceCacheMemory) getAllVersions() []PairedVersion {
if len(c.vMap) == 0 {
return nil
}
vlist := make([]PairedVersion, 0, len(c.vMap))
for v, r := range c.vMap {
vlist = append(vlist, v.Pair(r))
func (c *singleSourceCacheMemory) getAllVersions() ([]PairedVersion, bool) {
c.mut.Lock()
vList := c.vList
c.mut.Unlock()

if vList == nil {
return nil, false
}
return vlist
cp := make([]PairedVersion, len(vList))
copy(cp, vList)
return cp, true
}

func (c *singleSourceCacheMemory) getRevisionFor(uv UnpairedVersion) (Revision, bool) {
Expand Down
8 changes: 4 additions & 4 deletions internal/gps/source_cache_bolt.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,7 @@ func (s *singleSourceCacheBolt) getVersionsFor(rev Revision) (uvs []UnpairedVers
return
}

func (s *singleSourceCacheBolt) getAllVersions() []PairedVersion {
var pvs []PairedVersion
func (s *singleSourceCacheBolt) getAllVersions() (pvs []PairedVersion, ok bool) {
err := s.viewSourceBucket(func(src *bolt.Bucket) error {
versions := cacheFindLatestValid(src, cacheVersion, s.epoch)
if versions == nil {
Expand All @@ -369,14 +368,15 @@ func (s *singleSourceCacheBolt) getAllVersions() []PairedVersion {
return err
}
pvs = append(pvs, uv.Pair(Revision(v)))
ok = true
return nil
})
})
if err != nil {
s.logger.Println(errors.Wrap(err, "failed to get all cached versions"))
return nil
return nil, false
}
return pvs
return
}

func (s *singleSourceCacheBolt) getRevisionFor(uv UnpairedVersion) (rev Revision, ok bool) {
Expand Down
16 changes: 8 additions & 8 deletions internal/gps/source_cache_bolt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ func TestBoltCacheTimeout(t *testing.T) {
}
comparePackageTree(t, ptree, got)

gotV := c.getAllVersions()
if len(gotV) != len(pvs) {
gotV, ok := c.getAllVersions()
if !ok || len(gotV) != len(pvs) {
t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", gotV, pvs)
} else {
SortPairedForDowngrade(gotV)
Expand Down Expand Up @@ -161,8 +161,8 @@ func TestBoltCacheTimeout(t *testing.T) {
}
comparePackageTree(t, ptree, gotPtree)

pvs := c.getAllVersions()
if len(pvs) > 0 {
pvs, ok := c.getAllVersions()
if ok || len(pvs) > 0 {
t.Errorf("expected no cached versions, but got:\n\t%#v", pvs)
}
}
Expand Down Expand Up @@ -194,8 +194,8 @@ func TestBoltCacheTimeout(t *testing.T) {
}
comparePackageTree(t, ptree, got)

gotV := c.getAllVersions()
if len(gotV) != len(pvs) {
gotV, ok := c.getAllVersions()
if !ok || len(gotV) != len(pvs) {
t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", gotV, pvs)
} else {
SortPairedForDowngrade(gotV)
Expand Down Expand Up @@ -282,8 +282,8 @@ func TestBoltCacheTimeout(t *testing.T) {
}
comparePackageTree(t, newPtree, got)

gotV := c.getAllVersions()
if len(gotV) != len(newPVS) {
gotV, ok := c.getAllVersions()
if !ok || len(gotV) != len(newPVS) {
t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", gotV, newPVS)
} else {
SortPairedForDowngrade(gotV)
Expand Down
16 changes: 8 additions & 8 deletions internal/gps/source_cache_multi.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,19 @@ func (c *multiCache) getVersionsFor(rev Revision) ([]UnpairedVersion, bool) {
return c.disk.getVersionsFor(rev)
}

func (c *multiCache) getAllVersions() []PairedVersion {
pvs := c.mem.getAllVersions()
if pvs != nil {
return pvs
func (c *multiCache) getAllVersions() ([]PairedVersion, bool) {
pvs, ok := c.mem.getAllVersions()
if ok {
return pvs, true
}

pvs = c.disk.getAllVersions()
if pvs != nil {
pvs, ok = c.disk.getAllVersions()
if ok {
c.mem.setVersionMap(pvs)
return pvs
return pvs, true
}

return nil
return nil, false
}

func (c *multiCache) getRevisionFor(uv UnpairedVersion) (Revision, bool) {
Expand Down
8 changes: 4 additions & 4 deletions internal/gps/source_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,8 @@ func (test singleSourceCacheTest) run(t *testing.T) {
}

t.Run("getAllVersions", func(t *testing.T) {
got := c.getAllVersions()
if len(got) != len(versions) {
got, ok := c.getAllVersions()
if !ok || len(got) != len(versions) {
t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", got, versions)
} else {
SortPairedForDowngrade(got)
Expand Down Expand Up @@ -566,8 +566,8 @@ func (discardCache) getVersionsFor(Revision) ([]UnpairedVersion, bool) {
return nil, false
}

func (discardCache) getAllVersions() []PairedVersion {
return nil
func (discardCache) getAllVersions() ([]PairedVersion, bool) {
return nil, false
}

func (discardCache) getRevisionFor(UnpairedVersion) (Revision, bool) {
Expand Down
4 changes: 2 additions & 2 deletions internal/gps/source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ func testSourceGateway(t *testing.T) {
t.Fatalf("error on cloning git repo: %s", err)
}

cvlist := sg.cache.getAllVersions()
if len(cvlist) != 4 {
cvlist, ok := sg.cache.getAllVersions()
if !ok || len(cvlist) != 4 {
t.Fatalf("repo setup should've cached four versions, got %v: %s", len(cvlist), cvlist)
}

Expand Down

0 comments on commit ac1a162

Please sign in to comment.