1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-06-08 23:56:15 +02:00

Speed up refresh using concurrency and wait groups

Previously our synchronous refreshes took far longer because nothing
was happening concurrently. We now run refresh functions concurrently
and use a wait group to ensure they're all done before returning
This commit is contained in:
Jesse Duffield 2023-07-29 09:34:17 +10:00
parent 272e021c08
commit 63e5790410

View File

@ -91,59 +91,70 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
scopeSet = set.NewFromSlice(options.Scope) scopeSet = set.NewFromSlice(options.Scope)
} }
refresh := func(f func()) { wg := sync.WaitGroup{}
refresh := func(name string, f func()) {
if options.Mode == types.ASYNC { if options.Mode == types.ASYNC {
self.c.OnWorker(func(t gocui.Task) { self.c.OnWorker(func(t gocui.Task) {
f() f()
}) })
} else { } else {
wg.Add(1)
go utils.Safe(func() {
t := time.Now()
defer wg.Done()
f() f()
self.c.Log.Infof(fmt.Sprintf("refreshed %s in %s", name, time.Since(t)))
})
} }
} }
if scopeSet.Includes(types.COMMITS) || scopeSet.Includes(types.BRANCHES) || scopeSet.Includes(types.REFLOG) || scopeSet.Includes(types.BISECT_INFO) { if scopeSet.Includes(types.COMMITS) || scopeSet.Includes(types.BRANCHES) || scopeSet.Includes(types.REFLOG) || scopeSet.Includes(types.BISECT_INFO) {
refresh(self.refreshCommits) // whenever we change commits, we should update branches because the upstream/downstream
// counts can change. Whenever we change branches we should also change commits
// e.g. in the case of switching branches.
refresh("commits and commit files", self.refreshCommitsAndCommitFiles)
refresh("reflog and branches", self.refreshReflogAndBranches)
} else if scopeSet.Includes(types.REBASE_COMMITS) { } else if scopeSet.Includes(types.REBASE_COMMITS) {
// the above block handles rebase commits so we only need to call this one // the above block handles rebase commits so we only need to call this one
// if we've asked specifically for rebase commits and not those other things // if we've asked specifically for rebase commits and not those other things
refresh(func() { _ = self.refreshRebaseCommits() }) refresh("rebase commits", func() { _ = self.refreshRebaseCommits() })
} }
if scopeSet.Includes(types.SUB_COMMITS) { if scopeSet.Includes(types.SUB_COMMITS) {
refresh(func() { _ = self.refreshSubCommitsWithLimit() }) refresh("sub commits", func() { _ = self.refreshSubCommitsWithLimit() })
} }
// reason we're not doing this if the COMMITS type is included is that if the COMMITS type _is_ included we will refresh the commit files context anyway // reason we're not doing this if the COMMITS type is included is that if the COMMITS type _is_ included we will refresh the commit files context anyway
if scopeSet.Includes(types.COMMIT_FILES) && !scopeSet.Includes(types.COMMITS) { if scopeSet.Includes(types.COMMIT_FILES) && !scopeSet.Includes(types.COMMITS) {
refresh(func() { _ = self.refreshCommitFilesContext() }) refresh("commit files", func() { _ = self.refreshCommitFilesContext() })
} }
if scopeSet.Includes(types.FILES) || scopeSet.Includes(types.SUBMODULES) { if scopeSet.Includes(types.FILES) || scopeSet.Includes(types.SUBMODULES) {
refresh(func() { _ = self.refreshFilesAndSubmodules() }) refresh("files", func() { _ = self.refreshFilesAndSubmodules() })
} }
if scopeSet.Includes(types.STASH) { if scopeSet.Includes(types.STASH) {
refresh(func() { _ = self.refreshStashEntries() }) refresh("stash", func() { _ = self.refreshStashEntries() })
} }
if scopeSet.Includes(types.TAGS) { if scopeSet.Includes(types.TAGS) {
refresh(func() { _ = self.refreshTags() }) refresh("tags", func() { _ = self.refreshTags() })
} }
if scopeSet.Includes(types.REMOTES) { if scopeSet.Includes(types.REMOTES) {
refresh(func() { _ = self.refreshRemotes() }) refresh("remotes", func() { _ = self.refreshRemotes() })
} }
if scopeSet.Includes(types.STAGING) { if scopeSet.Includes(types.STAGING) {
refresh(func() { _ = self.stagingHelper.RefreshStagingPanel(types.OnFocusOpts{}) }) refresh("staging", func() { _ = self.stagingHelper.RefreshStagingPanel(types.OnFocusOpts{}) })
} }
if scopeSet.Includes(types.PATCH_BUILDING) { if scopeSet.Includes(types.PATCH_BUILDING) {
refresh(func() { _ = self.patchBuildingHelper.RefreshPatchBuildingPanel(types.OnFocusOpts{}) }) refresh("patch building", func() { _ = self.patchBuildingHelper.RefreshPatchBuildingPanel(types.OnFocusOpts{}) })
} }
if scopeSet.Includes(types.MERGE_CONFLICTS) || scopeSet.Includes(types.FILES) { if scopeSet.Includes(types.MERGE_CONFLICTS) || scopeSet.Includes(types.FILES) {
refresh(func() { _ = self.mergeConflictsHelper.RefreshMergeState() }) refresh("merge conflicts", func() { _ = self.mergeConflictsHelper.RefreshMergeState() })
} }
self.refreshStatus() self.refreshStatus()
@ -151,6 +162,8 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
if options.Then != nil { if options.Then != nil {
options.Then() options.Then()
} }
wg.Wait()
} }
if options.Mode == types.BLOCK_UI { if options.Mode == types.BLOCK_UI {
@ -218,21 +231,13 @@ func (self *RefreshHelper) refreshReflogCommitsConsideringStartup() {
} }
} }
// whenever we change commits, we should update branches because the upstream/downstream func (self *RefreshHelper) refreshReflogAndBranches() {
// counts can change. Whenever we change branches we should probably also change commits
// e.g. in the case of switching branches.
func (self *RefreshHelper) refreshCommits() {
wg := sync.WaitGroup{}
wg.Add(2)
go utils.Safe(func() {
self.refreshReflogCommitsConsideringStartup() self.refreshReflogCommitsConsideringStartup()
self.refreshBranches() self.refreshBranches()
wg.Done() }
})
go utils.Safe(func() { func (self *RefreshHelper) refreshCommitsAndCommitFiles() {
_ = self.refreshCommitsWithLimit() _ = self.refreshCommitsWithLimit()
ctx, ok := self.c.Contexts().CommitFiles.GetParentContext() ctx, ok := self.c.Contexts().CommitFiles.GetParentContext()
if ok && ctx.GetKey() == context.LOCAL_COMMITS_CONTEXT_KEY { if ok && ctx.GetKey() == context.LOCAL_COMMITS_CONTEXT_KEY {
@ -249,10 +254,6 @@ func (self *RefreshHelper) refreshCommits() {
_ = self.refreshCommitFilesContext() _ = self.refreshCommitFilesContext()
} }
} }
wg.Done()
})
wg.Wait()
} }
func (self *RefreshHelper) refreshCommitsWithLimit() error { func (self *RefreshHelper) refreshCommitsWithLimit() error {