Speed up GetPage

```
name                             old time/op    new time/op    delta
GetPage-10                          413ns ± 0%     287ns ± 1%  -30.47%  (p=0.029 n=4+4)
GetPageRegular/From_root-10         757ns ± 1%     706ns ± 1%   -6.75%  (p=0.029 n=4+4)
GetPageRegular/Page_relative-10     838ns ± 1%     786ns ± 1%   -6.16%  (p=0.029 n=4+4)

name                             old alloc/op   new alloc/op   delta
GetPage-10                           312B ± 0%       24B ± 0%  -92.31%  (p=0.029 n=4+4)
GetPageRegular/From_root-10          328B ± 0%      200B ± 0%  -39.02%  (p=0.029 n=4+4)
GetPageRegular/Page_relative-10      360B ± 0%      232B ± 0%  -35.56%  (p=0.029 n=4+4)

name                             old allocs/op  new allocs/op  delta
GetPage-10                           8.00 ± 0%      2.00 ± 0%  -75.00%  (p=0.029 n=4+4)
GetPageRegular/From_root-10          7.00 ± 0%      5.00 ± 0%  -28.57%  (p=0.029 n=4+4)
GetPageRegular/Page_relative-10      9.00 ± 0%      7.00 ± 0%  -22.22%  (p=0.029 n=4+4)
```
This commit is contained in:
Bjørn Erik Pedersen 2024-02-23 15:01:19 +01:00
parent f521336c81
commit bf14d0cb26
2 changed files with 37 additions and 22 deletions

View file

@ -54,15 +54,27 @@ func NormalizePathStringBasic(s string) string {
// ParseIdentity parses component c with path s into a StringIdentity. // ParseIdentity parses component c with path s into a StringIdentity.
func (pp *PathParser) ParseIdentity(c, s string) identity.StringIdentity { func (pp *PathParser) ParseIdentity(c, s string) identity.StringIdentity {
p := pp.parsePooled(c, s)
defer putPath(p)
return identity.StringIdentity(p.IdentifierBase())
}
// ParseBaseAndBaseNameNoIdentifier parses component c with path s into a base and a base name without any identifier.
func (pp *PathParser) ParseBaseAndBaseNameNoIdentifier(c, s string) (string, string) {
p := pp.parsePooled(c, s)
defer putPath(p)
return p.Base(), p.BaseNameNoIdentifier()
}
func (pp *PathParser) parsePooled(c, s string) *Path {
s = NormalizePathStringBasic(s) s = NormalizePathStringBasic(s)
p := getPath() p := getPath()
p.component = c p.component = c
defer putPath(p)
p, err := pp.doParse(c, s, p) p, err := pp.doParse(c, s, p)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return identity.StringIdentity(p.IdentifierBase()) return p
} }
// Parse parses component c with path s into Path using Hugo's content path rules. // Parse parses component c with path s into Path using Hugo's content path rules.
@ -259,7 +271,9 @@ type Path struct {
var pathPool = &sync.Pool{ var pathPool = &sync.Pool{
New: func() any { New: func() any {
return &Path{} p := &Path{}
p.reset()
return p
}, },
} }
@ -268,6 +282,11 @@ func getPath() *Path {
} }
func putPath(p *Path) { func putPath(p *Path) {
p.reset()
pathPool.Put(p)
}
func (p *Path) reset() {
p.s = "" p.s = ""
p.posContainerLow = -1 p.posContainerLow = -1
p.posContainerHigh = -1 p.posContainerHigh = -1
@ -279,7 +298,6 @@ func putPath(p *Path) {
p.disabled = false p.disabled = false
p.trimLeadingSlash = false p.trimLeadingSlash = false
p.unnormalized = nil p.unnormalized = nil
pathPool.Put(p)
} }
// TrimLeadingSlash returns a copy of the Path with the leading slash removed. // TrimLeadingSlash returns a copy of the Path with the leading slash removed.

View file

@ -131,22 +131,21 @@ func (c *pageFinder) getContentNode(context page.Page, isReflink bool, ref strin
return c.getContentNodeForRef(context, isReflink, true, inRef, ref) return c.getContentNodeForRef(context, isReflink, true, inRef, ref)
} }
var refs []string
// We are always looking for a content file and having an extension greatly simplifies the code that follows, // We are always looking for a content file and having an extension greatly simplifies the code that follows,
// even in the case where the extension does not match this one. // even in the case where the extension does not match this one.
if ref == "/" { if ref == "/" {
refs = append(refs, "/_index"+defaultContentExt) if n, err := c.getContentNodeForRef(context, isReflink, false, inRef, "/_index"+defaultContentExt); n != nil || err != nil {
} else if strings.HasSuffix(ref, "/index") { return n, err
refs = append(refs, ref+"/index"+defaultContentExt)
refs = append(refs, ref+defaultContentExt)
} else {
refs = append(refs, ref+defaultContentExt)
} }
} else if strings.HasSuffix(ref, "/index") {
for _, ref := range refs { if n, err := c.getContentNodeForRef(context, isReflink, false, inRef, ref+"/index"+defaultContentExt); n != nil || err != nil {
n, err := c.getContentNodeForRef(context, isReflink, false, inRef, ref) return n, err
if n != nil || err != nil { }
if n, err := c.getContentNodeForRef(context, isReflink, false, inRef, ref+defaultContentExt); n != nil || err != nil {
return n, err
}
} else {
if n, err := c.getContentNodeForRef(context, isReflink, false, inRef, ref+defaultContentExt); n != nil || err != nil {
return n, err return n, err
} }
} }
@ -175,7 +174,7 @@ func (c *pageFinder) getContentNodeForRef(context page.Page, isReflink, hadExten
rel := path.Join(baseDir, ref) rel := path.Join(baseDir, ref)
relPath := contentPathParser.Parse(files.ComponentFolderContent, rel) relPath, _ := contentPathParser.ParseBaseAndBaseNameNoIdentifier(files.ComponentFolderContent, rel)
n, err := c.getContentNodeFromPath(relPath, ref) n, err := c.getContentNodeFromPath(relPath, ref)
if n != nil || err != nil { if n != nil || err != nil {
@ -195,9 +194,9 @@ func (c *pageFinder) getContentNodeForRef(context page.Page, isReflink, hadExten
return nil, nil return nil, nil
} }
refPath := contentPathParser.Parse(files.ComponentFolderContent, ref) relPath, nameNoIdentifier := contentPathParser.ParseBaseAndBaseNameNoIdentifier(files.ComponentFolderContent, ref)
n, err := c.getContentNodeFromPath(refPath, ref) n, err := c.getContentNodeFromPath(relPath, ref)
if n != nil || err != nil { if n != nil || err != nil {
return n, err return n, err
@ -221,7 +220,7 @@ func (c *pageFinder) getContentNodeForRef(context page.Page, isReflink, hadExten
return nil, nil return nil, nil
} }
n = c.pageMap.pageReverseIndex.Get(refPath.BaseNameNoIdentifier()) n = c.pageMap.pageReverseIndex.Get(nameNoIdentifier)
if n == ambiguousContentNode { if n == ambiguousContentNode {
return nil, fmt.Errorf("page reference %q is ambiguous", inRef) return nil, fmt.Errorf("page reference %q is ambiguous", inRef)
} }
@ -254,9 +253,7 @@ func (c *pageFinder) getContentNodeFromRefReverseLookup(ref string, fi hugofs.Fi
return nil, nil return nil, nil
} }
func (c *pageFinder) getContentNodeFromPath(refPath *paths.Path, ref string) (contentNodeI, error) { func (c *pageFinder) getContentNodeFromPath(s string, ref string) (contentNodeI, error) {
s := refPath.Base()
n := c.pageMap.treePages.Get(s) n := c.pageMap.treePages.Get(s)
if n != nil { if n != nil {
return n, nil return n, nil