perf: Various performance regression fixes (#38078)
Fixes five N+1 / O(n) query patterns found across common user paths.
Each uses a bulk query that already existed elsewhere in the codebase.
| Location | Problem | Introduced in |
| -------------------------------- |
-------------------------------------------------------------------------------------------------------------------------------
| ------------- |
| `IssueList.LoadIsRead` | `.In("issue_id")` missing its arg — xorm
generates `WHERE 0=1`, so `IsRead` is **never** set; every issue always
appears unread | #29515 |
| `ParseCommitsWithStatus` | `GetLatestCommitStatus` called once per
commit (O(n) queries on commit list / PR commits tab) | #33605 |
| `getReleaseInfos` (release list) | `GetLatestCommitStatus` called once
per release for CI badges | #29149 |
| User milestone dashboard | O(n×m) nested loop matching milestones to
repos | #26300 |
| `findCodeComments` (PR diff) | `LoadResolveDoer` + `LoadReactions`
called per inline comment — up to ~150 queries on a PR with 50 comments
| #20821 |
---------
Co-authored-by: Lauris B <lauris@nix.lv>
This commit is contained in:
@@ -101,6 +101,19 @@ func getReleaseInfos(ctx *context.Context, opts *repo_model.FindReleasesOptions)
|
||||
|
||||
canReadActions := ctx.Repo.Permission.CanRead(unit.TypeActions)
|
||||
|
||||
// Bulk-load commit statuses for all releases in one query.
|
||||
var commitStatusMap map[string][]*git_model.CommitStatus
|
||||
if canReadActions && len(releases) > 0 {
|
||||
shas := make([]string, 0, len(releases))
|
||||
for _, r := range releases {
|
||||
shas = append(shas, r.Sha1)
|
||||
}
|
||||
commitStatusMap, err = git_model.GetLatestCommitStatusForRepoCommitIDs(ctx, ctx.Repo.Repository.ID, shas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
releaseInfos := make([]*ReleaseInfo, 0, len(releases))
|
||||
for _, r := range releases {
|
||||
if r.Publisher, ok = cacheUsers[r.PublisherID]; !ok {
|
||||
@@ -130,11 +143,7 @@ func getReleaseInfos(ctx *context.Context, opts *repo_model.FindReleasesOptions)
|
||||
}
|
||||
|
||||
if canReadActions {
|
||||
statuses, err := git_model.GetLatestCommitStatus(ctx, r.Repo.ID, r.Sha1, db.ListOptionsAll)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
statuses := commitStatusMap[r.Sha1]
|
||||
info.CommitStatus = git_model.CalcCommitStatus(statuses)
|
||||
info.CommitStatuses = statuses
|
||||
}
|
||||
|
||||
@@ -242,13 +242,13 @@ func Milestones(ctx *context.Context) {
|
||||
}
|
||||
sort.Sort(showRepos)
|
||||
|
||||
repoByID := make(map[int64]*repo_model.Repository, len(showRepos))
|
||||
for _, repo := range showRepos {
|
||||
repoByID[repo.ID] = repo
|
||||
}
|
||||
|
||||
for i := 0; i < len(milestones); {
|
||||
for _, repo := range showRepos {
|
||||
if milestones[i].RepoID == repo.ID {
|
||||
milestones[i].Repo = repo
|
||||
break
|
||||
}
|
||||
}
|
||||
milestones[i].Repo = repoByID[milestones[i].RepoID]
|
||||
if milestones[i].Repo == nil {
|
||||
log.Warn("Cannot find milestone %d 's repository %d", milestones[i].ID, milestones[i].RepoID)
|
||||
milestones = append(milestones[:i], milestones[i+1:]...)
|
||||
|
||||
Reference in New Issue
Block a user