From 50d11138f3e18b545c15fadf52f7b0b744bf3e7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Thu, 25 May 2017 21:13:03 +0300 Subject: [PATCH] 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% ``` --- hugolib/page.go | 5 +- hugolib/page_collections.go | 104 +++++++++++++++++------------------- 2 files changed, 51 insertions(+), 58 deletions(-) diff --git a/hugolib/page.go b/hugolib/page.go index 8de4ad924..6bf42cb24 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -42,8 +42,9 @@ import ( ) 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 ( diff --git a/hugolib/page_collections.go b/hugolib/page_collections.go index 46491d59b..893286871 100644 --- a/hugolib/page_collections.go +++ b/hugolib/page_collections.go @@ -15,6 +15,9 @@ package hugolib import ( "path" + "path/filepath" + + "github.com/spf13/hugo/cache" ) // PageCollections contains the page collections for a site. @@ -39,12 +42,46 @@ type PageCollections struct { // Includes absolute all pages (of all types), including drafts etc. rawAllPages Pages + + pageCache *cache.PartitionedLazyCache } func (c *PageCollections) refreshPageCaches() { c.indexPages = c.findPagesByKindNotIn(KindPage, c.Pages) c.RegularPages = c.findPagesByKindIn(KindPage, c.Pages) c.AllRegularPages = c.findPagesByKindIn(KindPage, c.AllPages) + + 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 + } + } + + return cache, nil + } + } + + var partitions []cache.Partition + + for _, kind := range allKindsInPages { + partitions = append(partitions, cache.Partition{Key: kind, Load: cacheLoader(kind)}) + } + + c.pageCache = cache.NewPartitionedLazyCache(partitions...) } func newPageCollections() *PageCollections { @@ -55,65 +92,20 @@ func newPageCollectionsFromPages(pages Pages) *PageCollections { return &PageCollections{rawAllPages: pages} } -func (c *PageCollections) getFirstPageMatchIn(pages Pages, typ string, pathElements ...string) *Page { +func (c *PageCollections) getPage(typ string, sections ...string) *Page { + var key string + if len(sections) == 1 { + key = filepath.ToSlash(sections[0]) + } else { + key = path.Join(sections...) + } - if len(pages) == 0 { + // TODO(bep) section error + p, _ := c.pageCache.Get(typ, key) + if p == nil { return nil } - - var filename string - if typ == KindPage { - filename = path.Join(pathElements...) - } - - 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 - } - } - - return nil - -} - -func (c *PageCollections) getRegularPage(filename string) { - -} - -func (c *PageCollections) getPage(typ string, path ...string) *Page { - var pages Pages - - if typ == KindPage { - pages = c.AllPages - } else { - pages = c.indexPages - } - - return c.getFirstPageMatchIn(pages, typ, path...) + return p.(*Page) }