Skip to content

Commit

Permalink
page: Add some concurrency to the building of the related page index
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bep committed Feb 22, 2023
1 parent 4346987 commit fa2d7ad
Showing 1 changed file with 29 additions and 1 deletion.
30 changes: 29 additions & 1 deletion resources/page/pages_related.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
Expand Down

0 comments on commit fa2d7ad

Please sign in to comment.