shithub: hugo

Download patch

ref: 50d11138f3e18b545c15fadf52f7b0b744bf3e7c
parent: e0c2e798201f75ae6e9a81a7442355288c2d141b
author: Bjørn Erik Pedersen <[email protected]>
date: Thu May 25 17:13:03 EDT 2017

hugolib: Add a cache to GetPage

Looks to be slightly slower with the low number of section pages, but the 1000 regular pages seem to add value.

```
benchmark                     old ns/op     new ns/op     delta
BenchmarkGetPage-4            97.7          145           +48.41%
BenchmarkGetPageRegular-4     7933          161           -97.97%

benchmark                     old allocs     new allocs     delta
BenchmarkGetPage-4            0              0              +0.00%
BenchmarkGetPageRegular-4     0              0              +0.00%

benchmark                     old bytes     new bytes     delta
BenchmarkGetPage-4            0             0             +0.00%
BenchmarkGetPageRegular-4     0             0             +0.00%
```

--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -42,8 +42,9 @@
 )
 
 var (
-	cjk      = regexp.MustCompile(`\p{Han}|\p{Hangul}|\p{Hiragana}|\p{Katakana}`)
-	allKinds = []string{KindPage, KindHome, KindSection, KindTaxonomy, KindTaxonomyTerm, kindRSS, kindSitemap, kindRobotsTXT, kind404}
+	cjk             = regexp.MustCompile(`\p{Han}|\p{Hangul}|\p{Hiragana}|\p{Katakana}`)
+	allKindsInPages = []string{KindPage, KindHome, KindSection, KindTaxonomy, KindTaxonomyTerm, kindRSS}
+	allKinds        = append(allKindsInPages, []string{kindSitemap, kindRobotsTXT, kind404}...)
 )
 
 const (
--- a/hugolib/page_collections.go
+++ b/hugolib/page_collections.go
@@ -15,6 +15,9 @@
 
 import (
 	"path"
+	"path/filepath"
+
+	"github.com/spf13/hugo/cache"
 )
 
 // PageCollections contains the page collections for a site.
@@ -39,6 +42,8 @@
 
 	// Includes absolute all pages (of all types), including drafts etc.
 	rawAllPages Pages
+
+	pageCache *cache.PartitionedLazyCache
 }
 
 func (c *PageCollections) refreshPageCaches() {
@@ -45,75 +50,62 @@
 	c.indexPages = c.findPagesByKindNotIn(KindPage, c.Pages)
 	c.RegularPages = c.findPagesByKindIn(KindPage, c.Pages)
 	c.AllRegularPages = c.findPagesByKindIn(KindPage, c.AllPages)
-}
 
-func newPageCollections() *PageCollections {
-	return &PageCollections{}
-}
+	cacheLoader := func(kind string) func() (map[string]interface{}, error) {
+		return func() (map[string]interface{}, error) {
+			cache := make(map[string]interface{})
+			switch kind {
+			case KindPage:
+				// Note that we deliberately use the pages from all sites
+				// in this cache, as we intend to use this in the ref and relref
+				// shortcodes. If the user says "sect/doc1.en.md", he/she knows
+				// what he/she is looking for.
+				for _, p := range c.AllRegularPages {
+					// TODO(bep) section
+					cache[filepath.ToSlash(p.Source.Path())] = p
+				}
+			default:
+				for _, p := range c.indexPages {
+					key := path.Join(p.sections...)
+					cache[key] = p
+				}
+			}
 
-func newPageCollectionsFromPages(pages Pages) *PageCollections {
-	return &PageCollections{rawAllPages: pages}
-}
-
-func (c *PageCollections) getFirstPageMatchIn(pages Pages, typ string, pathElements ...string) *Page {
-
-	if len(pages) == 0 {
-		return nil
+			return cache, nil
+		}
 	}
 
-	var filename string
-	if typ == KindPage {
-		filename = path.Join(pathElements...)
-	}
+	var partitions []cache.Partition
 
-	for _, p := range pages {
-		if p.Kind != typ {
-			continue
-		}
-
-		if typ == KindHome {
-			return p
-		}
-
-		if typ == KindPage {
-			if p.Source.Path() == filename {
-				return p
-			}
-			continue
-		}
-
-		match := false
-		for i := 0; i < len(pathElements); i++ {
-			if len(p.sections) > i && pathElements[i] == p.sections[i] {
-				match = true
-			} else {
-				match = false
-				break
-			}
-		}
-		if match {
-			return p
-		}
+	for _, kind := range allKindsInPages {
+		partitions = append(partitions, cache.Partition{Key: kind, Load: cacheLoader(kind)})
 	}
 
-	return nil
+	c.pageCache = cache.NewPartitionedLazyCache(partitions...)
+}
 
+func newPageCollections() *PageCollections {
+	return &PageCollections{}
 }
 
-func (c *PageCollections) getRegularPage(filename string) {
-
+func newPageCollectionsFromPages(pages Pages) *PageCollections {
+	return &PageCollections{rawAllPages: pages}
 }
 
-func (c *PageCollections) getPage(typ string, path ...string) *Page {
-	var pages Pages
-
-	if typ == KindPage {
-		pages = c.AllPages
+func (c *PageCollections) getPage(typ string, sections ...string) *Page {
+	var key string
+	if len(sections) == 1 {
+		key = filepath.ToSlash(sections[0])
 	} else {
-		pages = c.indexPages
+		key = path.Join(sections...)
 	}
 
-	return c.getFirstPageMatchIn(pages, typ, path...)
+	// TODO(bep) section error
+	p, _ := c.pageCache.Get(typ, key)
+	if p == nil {
+		return nil
+	}
+	return p.(*Page)
 
 }