From fa2d7adf102d2dec9ebc52b5bc6b161bbb07b726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Wed, 22 Feb 2023 18:37:46 +0100 Subject: [PATCH] page: Add some concurrency to the building of the related page index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit But only in the case where we know that we will need to access the Page fragments/tableofcontents. In normal situations this will spread naturally across the CPU cores, but not in the situation where `site.RegularPages.Related` gets called as part of e.g. the single template. ```bash name old time/op new time/op delta RelatedSite-10 18.0ms ± 2% 11.9ms ± 1% -34.17% (p=0.029 n=4+4) name old alloc/op new alloc/op delta RelatedSite-10 38.6MB ± 0% 38.6MB ± 0% ~ (p=0.114 n=4+4) name old allocs/op new allocs/op delta RelatedSite-10 117k ± 0% 117k ± 0% +0.23% (p=0.029 n=4+4) ``` See #10711 --- resources/page/pages_related.go | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/resources/page/pages_related.go b/resources/page/pages_related.go index 74bb1713e..3378eb160 100644 --- a/resources/page/pages_related.go +++ b/resources/page/pages_related.go @@ -18,7 +18,9 @@ import ( "fmt" "sync" + "github.com/gohugoio/hugo/common/para" "github.com/gohugoio/hugo/common/types" + "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/related" "github.com/mitchellh/mapstructure" "github.com/spf13/cast" @@ -163,10 +165,12 @@ type RelatedDocsHandler struct { postingLists []*cachedPostingList mu sync.RWMutex + + workers *para.Workers } func NewRelatedDocsHandler(cfg related.Config) *RelatedDocsHandler { - return &RelatedDocsHandler{cfg: cfg} + return &RelatedDocsHandler{cfg: cfg, workers: para.New(config.GetNumWorkerMultiplier())} } func (s *RelatedDocsHandler) Clone() *RelatedDocsHandler { @@ -194,6 +198,30 @@ func (s *RelatedDocsHandler) getOrCreateIndex(ctx context.Context, p Pages) (*re s.mu.Lock() defer s.mu.Unlock() + for _, c := range s.cfg.Indices { + if c.Type == related.TypeFragments { + // This will trigger building the Pages' fragment map. + g, _ := s.workers.Start(ctx) + for _, page := range p { + fp, ok := page.(related.FragmentProvider) + if !ok { + continue + } + g.Run(func() error { + fp.Fragments(ctx) + return nil + }) + } + + if err := g.Wait(); err != nil { + return nil, err + } + + break + } + + } + if cachedIndex := s.getIndex(p); cachedIndex != nil { return cachedIndex, nil }