Only create LazyContentProvider for the non-rendering Site

Which saves a fair amound of allocations:

```
gobench --package ./hugolib --bench "SiteNew/Regular_D" --base master
```

Before:

```
name                                  old time/op    new time/op    delta
SiteNew/Regular_Deep_content_tree-10    40.7ms ± 3%    41.2ms ± 1%    ~     (p=0.343 n=4+4)

name                                  old alloc/op   new alloc/op   delta
SiteNew/Regular_Deep_content_tree-10    27.7MB ± 0%    28.8MB ± 0%  +3.76%  (p=0.029 n=4+4)

name                                  old allocs/op  new allocs/op  delta
SiteNew/Regular_Deep_content_tree-10      304k ± 0%      329k ± 0%  +8.07%  (p=0.029 n=4+4)
```

After:

```
name                                  old time/op    new time/op    delta
SiteNew/Regular_Deep_content_tree-10    34.2ms ± 1%    34.7ms ± 1%    ~     (p=0.114 n=4+4)

name                                  old alloc/op   new alloc/op   delta
SiteNew/Regular_Deep_content_tree-10    27.7MB ± 0%    28.1MB ± 0%  +1.38%  (p=0.029 n=4+4)

name                                  old allocs/op  new allocs/op  delta
SiteNew/Regular_Deep_content_tree-10      304k ± 0%      314k ± 0%  +3.03%  (p=0.029 n=4+4)
```

Updates #8919
This commit is contained in:
Bjørn Erik Pedersen 2022-01-11 17:32:58 +01:00
parent 25d645f47a
commit cdcd15b6c2
No known key found for this signature in database
GPG key ID: 330E6E2BD4859D8F
2 changed files with 22 additions and 21 deletions

View file

@ -940,20 +940,6 @@ func (p *pageState) shiftToOutputFormat(isRenderingSite bool, idx int) error {
panic(fmt.Sprintf("pageOutput is nil for output idx %d", idx)) panic(fmt.Sprintf("pageOutput is nil for output idx %d", idx))
} }
// We attempt to assign pageContentOutputs while preparing each site
// for rendering and before rendering each site. This lets us share
// content between page outputs to conserve resources. But if a template
// unexpectedly calls a method of a ContentProvider that is not yet
// initialized, we assign a LazyContentProvider that performs the
// initialization just in time.
p.pageOutput.ContentProvider = page.NewLazyContentProvider(func() (page.ContentProvider, error) {
cp, err := newPageContentOutput(p, p.pageOutput)
if err != nil {
return nil, err
}
return cp, nil
})
// Reset any built paginator. This will trigger when re-rendering pages in // Reset any built paginator. This will trigger when re-rendering pages in
// server mode. // server mode.
if isRenderingSite && p.pageOutput.paginator != nil && p.pageOutput.paginator.current != nil { if isRenderingSite && p.pageOutput.paginator != nil && p.pageOutput.paginator.current != nil {
@ -985,7 +971,24 @@ func (p *pageState) shiftToOutputFormat(isRenderingSite bool, idx int) error {
} }
} }
p.pageOutput.initContentProvider(cp) p.pageOutput.initContentProvider(cp)
p.pageOutput.cp = cp } else {
// We attempt to assign pageContentOutputs while preparing each site
// for rendering and before rendering each site. This lets us share
// content between page outputs to conserve resources. But if a template
// unexpectedly calls a method of a ContentProvider that is not yet
// initialized, we assign a LazyContentProvider that performs the
// initialization just in time.
if lcp, ok := (p.pageOutput.ContentProvider.(*page.LazyContentProvider)); ok {
lcp.Reset()
} else {
p.pageOutput.ContentProvider = page.NewLazyContentProvider(func() (page.ContentProvider, error) {
cp, err := newPageContentOutput(p, p.pageOutput)
if err != nil {
return nil, err
}
return cp, nil
})
}
} }
return nil return nil

View file

@ -49,6 +49,10 @@ func NewLazyContentProvider(f func() (ContentProvider, error)) *LazyContentProvi
return &lcp return &lcp
} }
func (lcp *LazyContentProvider) Reset() {
lcp.init.Reset()
}
func (lcp *LazyContentProvider) Content() (interface{}, error) { func (lcp *LazyContentProvider) Content() (interface{}, error) {
lcp.init.Do() lcp.init.Do()
return lcp.cp.Content() return lcp.cp.Content()
@ -67,35 +71,29 @@ func (lcp *LazyContentProvider) PlainWords() []string {
func (lcp *LazyContentProvider) Summary() template.HTML { func (lcp *LazyContentProvider) Summary() template.HTML {
lcp.init.Do() lcp.init.Do()
return lcp.cp.Summary() return lcp.cp.Summary()
} }
func (lcp *LazyContentProvider) Truncated() bool { func (lcp *LazyContentProvider) Truncated() bool {
lcp.init.Do() lcp.init.Do()
return lcp.cp.Truncated() return lcp.cp.Truncated()
} }
func (lcp *LazyContentProvider) FuzzyWordCount() int { func (lcp *LazyContentProvider) FuzzyWordCount() int {
lcp.init.Do() lcp.init.Do()
return lcp.cp.FuzzyWordCount() return lcp.cp.FuzzyWordCount()
} }
func (lcp *LazyContentProvider) WordCount() int { func (lcp *LazyContentProvider) WordCount() int {
lcp.init.Do() lcp.init.Do()
return lcp.cp.WordCount() return lcp.cp.WordCount()
} }
func (lcp *LazyContentProvider) ReadingTime() int { func (lcp *LazyContentProvider) ReadingTime() int {
lcp.init.Do() lcp.init.Do()
return lcp.cp.ReadingTime() return lcp.cp.ReadingTime()
} }
func (lcp *LazyContentProvider) Len() int { func (lcp *LazyContentProvider) Len() int {
lcp.init.Do() lcp.init.Do()
return lcp.cp.Len() return lcp.cp.Len()
} }