mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 02:46:04 +01:00 
			
		
		
		
	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>
This commit is contained in:
		| @@ -102,10 +102,13 @@ func (tes Entries) GetCommitsInfo(commit *Commit, treePath string, cache *LastCo | |||||||
| } | } | ||||||
|  |  | ||||||
| func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cache *LastCommitCache) (map[string]*Commit, []string, error) { | func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cache *LastCommitCache) (map[string]*Commit, []string, error) { | ||||||
|  | 	wr, rd, cancel := CatFileBatch(cache.repo.Path) | ||||||
|  | 	defer cancel() | ||||||
|  |  | ||||||
| 	var unHitEntryPaths []string | 	var unHitEntryPaths []string | ||||||
| 	var results = make(map[string]*Commit) | 	var results = make(map[string]*Commit) | ||||||
| 	for _, p := range paths { | 	for _, p := range paths { | ||||||
| 		lastCommit, err := cache.Get(commitID, path.Join(treePath, p)) | 		lastCommit, err := cache.Get(commitID, path.Join(treePath, p), wr, rd) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, nil, err | 			return nil, nil, err | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -7,6 +7,8 @@ | |||||||
| package git | package git | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"bufio" | ||||||
|  | 	"io" | ||||||
| 	"path" | 	"path" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -34,7 +36,7 @@ func NewLastCommitCache(repoPath string, gitRepo *Repository, ttl func() int64, | |||||||
| } | } | ||||||
|  |  | ||||||
| // Get get the last commit information by commit id and entry path | // Get get the last commit information by commit id and entry path | ||||||
| func (c *LastCommitCache) Get(ref, entryPath string) (interface{}, error) { | func (c *LastCommitCache) Get(ref, entryPath string, wr *io.PipeWriter, rd *bufio.Reader) (interface{}, error) { | ||||||
| 	v := c.cache.Get(c.getCacheKey(c.repoPath, ref, entryPath)) | 	v := c.cache.Get(c.getCacheKey(c.repoPath, ref, entryPath)) | ||||||
| 	if vs, ok := v.(string); ok { | 	if vs, ok := v.(string); ok { | ||||||
| 		log("LastCommitCache hit level 1: [%s:%s:%s]", ref, entryPath, vs) | 		log("LastCommitCache hit level 1: [%s:%s:%s]", ref, entryPath, vs) | ||||||
| @@ -46,7 +48,10 @@ func (c *LastCommitCache) Get(ref, entryPath string) (interface{}, error) { | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| 		commit, err := c.repo.getCommit(id) | 		if _, err := wr.Write([]byte(vs + "\n")); err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		commit, err := c.repo.getCommitFromBatchReader(rd, id) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -9,9 +9,10 @@ package git | |||||||
| import ( | import ( | ||||||
| 	"bufio" | 	"bufio" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" |  | ||||||
| 	"io" | 	"io" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
|  | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -34,6 +35,18 @@ func (repo *Repository) ResolveReference(name string) (string, error) { | |||||||
|  |  | ||||||
| // GetRefCommitID returns the last commit ID string of given reference (branch or tag). | // GetRefCommitID returns the last commit ID string of given reference (branch or tag). | ||||||
| func (repo *Repository) GetRefCommitID(name string) (string, error) { | func (repo *Repository) GetRefCommitID(name string) (string, error) { | ||||||
|  | 	if strings.HasPrefix(name, "refs/") { | ||||||
|  | 		// We're gonna try just reading the ref file as this is likely to be quicker than other options | ||||||
|  | 		fileInfo, err := os.Lstat(filepath.Join(repo.Path, name)) | ||||||
|  | 		if err == nil && fileInfo.Mode().IsRegular() && fileInfo.Size() == 41 { | ||||||
|  | 			ref, err := ioutil.ReadFile(filepath.Join(repo.Path, name)) | ||||||
|  |  | ||||||
|  | 			if err == nil && SHAPattern.Match(ref[:40]) && ref[40] == '\n' { | ||||||
|  | 				return string(ref[:40]), nil | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	stdout, err := NewCommand("show-ref", "--verify", "--hash", name).RunInDir(repo.Path) | 	stdout, err := NewCommand("show-ref", "--verify", "--hash", name).RunInDir(repo.Path) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if strings.Contains(err.Error(), "not a valid ref") { | 		if strings.Contains(err.Error(), "not a valid ref") { | ||||||
| @@ -69,6 +82,11 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) { | |||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| 	bufReader := bufio.NewReader(stdoutReader) | 	bufReader := bufio.NewReader(stdoutReader) | ||||||
|  |  | ||||||
|  | 	return repo.getCommitFromBatchReader(bufReader, id) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (repo *Repository) getCommitFromBatchReader(bufReader *bufio.Reader, id SHA1) (*Commit, error) { | ||||||
| 	_, typ, size, err := ReadBatchLine(bufReader) | 	_, typ, size, err := ReadBatchLine(bufReader) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if errors.Is(err, io.EOF) { | 		if errors.Is(err, io.EOF) { | ||||||
| @@ -106,7 +124,6 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) { | |||||||
| 	case "commit": | 	case "commit": | ||||||
| 		return CommitFromReader(repo, id, io.LimitReader(bufReader, size)) | 		return CommitFromReader(repo, id, io.LimitReader(bufReader, size)) | ||||||
| 	default: | 	default: | ||||||
| 		_ = stdoutReader.CloseWithError(fmt.Errorf("unknown typ: %s", typ)) |  | ||||||
| 		log("Unknown typ: %s", typ) | 		log("Unknown typ: %s", typ) | ||||||
| 		return nil, ErrNotExist{ | 		return nil, ErrNotExist{ | ||||||
| 			ID: id.String(), | 			ID: id.String(), | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user