From 6764d678a52c8362b44a8f1be96546a12fa7748b Mon Sep 17 00:00:00 2001 From: Suleiman Dibirov Date: Sun, 16 Jun 2024 09:53:36 +0300 Subject: [PATCH] perf(manager.go): optimize load chart repositories with concurrent processing Signed-off-by: Suleiman Dibirov --- pkg/downloader/manager.go | 49 ++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index 68c9c6e00..28b54b22a 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -31,6 +31,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/pkg/errors" + "golang.org/x/sync/errgroup" "sigs.k8s.io/yaml" "helm.sh/helm/v3/internal/resolver" @@ -241,6 +242,7 @@ func (m *Manager) resolve(req []*chart.Dependency, repoNames map[string]string) // a conflict. func (m *Manager) downloadAll(deps []*chart.Dependency) error { repos, err := m.loadChartRepositories() + if err != nil { return err } @@ -660,7 +662,6 @@ func (m *Manager) UpdateRepositories() error { } func (m *Manager) parallelRepoUpdate(repos []*repo.Entry) error { - var wg sync.WaitGroup for _, c := range repos { r, err := repo.NewChartRepository(c, m.Getters) @@ -670,6 +671,8 @@ func (m *Manager) parallelRepoUpdate(repos []*repo.Entry) error { r.CachePath = m.RepositoryCache wg.Add(1) go func(r *repo.ChartRepository) { + defer wg.Done() + if _, err := r.DownloadIndexFile(); err != nil { // For those dependencies that are not known to helm and using a // generated key name we display the repo url. @@ -687,7 +690,6 @@ func (m *Manager) parallelRepoUpdate(repos []*repo.Entry) error { fmt.Fprintf(m.Out, "...Successfully got an update from the %q chart repository\n", r.Config.Name) } } - wg.Done() }(r) } wg.Wait() @@ -823,21 +825,40 @@ func (m *Manager) loadChartRepositories() (map[string]*repo.ChartRepository, err return indices, errors.Wrapf(err, "failed to load %s", m.RepositoryConfig) } + var ( + g errgroup.Group + mu sync.Mutex + ) for _, re := range rf.Repositories { - lname := re.Name - idxFile := filepath.Join(m.RepositoryCache, helmpath.CacheIndexFile(lname)) - index, err := repo.LoadIndexFile(idxFile) - if err != nil { - return indices, err - } + re := re - // TODO: use constructor - cr := &repo.ChartRepository{ - Config: re, - IndexFile: index, - } - indices[lname] = cr + g.Go(func() error { + lname := re.Name + idxFile := filepath.Join(m.RepositoryCache, helmpath.CacheIndexFile(lname)) + index, err := repo.LoadIndexFile(idxFile) + if err != nil { + return err + } + + // TODO: use constructor + cr := &repo.ChartRepository{ + Config: re, + IndexFile: index, + } + + mu.Lock() + indices[lname] = cr + mu.Unlock() + + return nil + }) } + + // Wait for all repositories to be loaded + if err := g.Wait(); err != nil { + return indices, err + } + return indices, nil }