Skip to content

Commit a926ff9

Browse files
authored
Performance improvement for last commit cache and show-ref (#15455)
* Improve performance when there are multiple commits in the last commit cache * read refs directly if we can Signed-off-by: Andrew Thornton <art27@cantab.net>
1 parent fda2e45 commit a926ff9

File tree

3 files changed

+30
-5
lines changed

3 files changed

+30
-5
lines changed

modules/git/commit_info_nogogit.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,13 @@ func (tes Entries) GetCommitsInfo(commit *Commit, treePath string, cache *LastCo
102102
}
103103

104104
func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cache *LastCommitCache) (map[string]*Commit, []string, error) {
105+
wr, rd, cancel := CatFileBatch(cache.repo.Path)
106+
defer cancel()
107+
105108
var unHitEntryPaths []string
106109
var results = make(map[string]*Commit)
107110
for _, p := range paths {
108-
lastCommit, err := cache.Get(commitID, path.Join(treePath, p))
111+
lastCommit, err := cache.Get(commitID, path.Join(treePath, p), wr, rd)
109112
if err != nil {
110113
return nil, nil, err
111114
}

modules/git/last_commit_cache_nogogit.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
package git
88

99
import (
10+
"bufio"
11+
"io"
1012
"path"
1113
)
1214

@@ -34,7 +36,7 @@ func NewLastCommitCache(repoPath string, gitRepo *Repository, ttl func() int64,
3436
}
3537

3638
// Get get the last commit information by commit id and entry path
37-
func (c *LastCommitCache) Get(ref, entryPath string) (interface{}, error) {
39+
func (c *LastCommitCache) Get(ref, entryPath string, wr *io.PipeWriter, rd *bufio.Reader) (interface{}, error) {
3840
v := c.cache.Get(c.getCacheKey(c.repoPath, ref, entryPath))
3941
if vs, ok := v.(string); ok {
4042
log("LastCommitCache hit level 1: [%s:%s:%s]", ref, entryPath, vs)
@@ -46,7 +48,10 @@ func (c *LastCommitCache) Get(ref, entryPath string) (interface{}, error) {
4648
if err != nil {
4749
return nil, err
4850
}
49-
commit, err := c.repo.getCommit(id)
51+
if _, err := wr.Write([]byte(vs + "\n")); err != nil {
52+
return nil, err
53+
}
54+
commit, err := c.repo.getCommitFromBatchReader(rd, id)
5055
if err != nil {
5156
return nil, err
5257
}

modules/git/repo_commit_nogogit.go

+19-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ package git
99
import (
1010
"bufio"
1111
"errors"
12-
"fmt"
1312
"io"
1413
"io/ioutil"
14+
"os"
15+
"path/filepath"
1516
"strings"
1617
)
1718

@@ -34,6 +35,18 @@ func (repo *Repository) ResolveReference(name string) (string, error) {
3435

3536
// GetRefCommitID returns the last commit ID string of given reference (branch or tag).
3637
func (repo *Repository) GetRefCommitID(name string) (string, error) {
38+
if strings.HasPrefix(name, "refs/") {
39+
// We're gonna try just reading the ref file as this is likely to be quicker than other options
40+
fileInfo, err := os.Lstat(filepath.Join(repo.Path, name))
41+
if err == nil && fileInfo.Mode().IsRegular() && fileInfo.Size() == 41 {
42+
ref, err := ioutil.ReadFile(filepath.Join(repo.Path, name))
43+
44+
if err == nil && SHAPattern.Match(ref[:40]) && ref[40] == '\n' {
45+
return string(ref[:40]), nil
46+
}
47+
}
48+
}
49+
3750
stdout, err := NewCommand("show-ref", "--verify", "--hash", name).RunInDir(repo.Path)
3851
if err != nil {
3952
if strings.Contains(err.Error(), "not a valid ref") {
@@ -69,6 +82,11 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
6982
}()
7083

7184
bufReader := bufio.NewReader(stdoutReader)
85+
86+
return repo.getCommitFromBatchReader(bufReader, id)
87+
}
88+
89+
func (repo *Repository) getCommitFromBatchReader(bufReader *bufio.Reader, id SHA1) (*Commit, error) {
7290
_, typ, size, err := ReadBatchLine(bufReader)
7391
if err != nil {
7492
if errors.Is(err, io.EOF) {
@@ -106,7 +124,6 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
106124
case "commit":
107125
return CommitFromReader(repo, id, io.LimitReader(bufReader, size))
108126
default:
109-
_ = stdoutReader.CloseWithError(fmt.Errorf("unknown typ: %s", typ))
110127
log("Unknown typ: %s", typ)
111128
return nil, ErrNotExist{
112129
ID: id.String(),

0 commit comments

Comments
 (0)