From 6178238a0b069ae8ce65a23e3dd60c091de0cfef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sat, 18 Mar 2017 16:46:10 +0100 Subject: output: Speed up layout calculations ``` BenchmarkLayout-4 4883 497 -89.82% benchmark old allocs new allocs delta BenchmarkLayout-4 18 1 -94.44% benchmark old bytes new bytes delta BenchmarkLayout-4 1624 32 -98.03% ``` --- output/layout.go | 26 +++++++++++++++++++++++++- output/layout_test.go | 11 +++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'output') diff --git a/output/layout.go b/output/layout.go index c33ce3f0c..833a6cf4a 100644 --- a/output/layout.go +++ b/output/layout.go @@ -17,6 +17,7 @@ import ( "fmt" "path" "strings" + "sync" ) // LayoutDescriptor describes how a layout should be chosen. This is @@ -32,10 +33,19 @@ type LayoutDescriptor struct { // TODO(bep) output improve names type LayoutHandler struct { hasTheme bool + + mu sync.RWMutex + cache map[layoutCacheKey][]string +} + +type layoutCacheKey struct { + d LayoutDescriptor + layoutOverride string + f Format } func NewLayoutHandler(hasTheme bool) *LayoutHandler { - return &LayoutHandler{hasTheme: hasTheme} + return &LayoutHandler{hasTheme: hasTheme, cache: make(map[layoutCacheKey][]string)} } const ( @@ -62,6 +72,16 @@ indexes/indexes.NAME.SUFFIX indexes/indexes.SUFFIX ) func (l *LayoutHandler) For(d LayoutDescriptor, layoutOverride string, f Format) []string { + + // We will get lots of requests for the same layouts, so avoid recalculations. + key := layoutCacheKey{d, layoutOverride, f} + l.mu.RLock() + if cacheVal, found := l.cache[key]; found { + l.mu.RUnlock() + return cacheVal + } + l.mu.RUnlock() + var layouts []string layout := d.Layout @@ -110,6 +130,10 @@ func (l *LayoutHandler) For(d LayoutDescriptor, layoutOverride string, f Format) return layoutsWithThemeLayouts } + l.mu.Lock() + l.cache[key] = layouts + l.mu.Unlock() + return layouts } diff --git a/output/layout_test.go b/output/layout_test.go index e678197ca..aa0657a36 100644 --- a/output/layout_test.go +++ b/output/layout_test.go @@ -73,4 +73,15 @@ func TestLayout(t *testing.T) { } }) } + +} + +func BenchmarkLayout(b *testing.B) { + descriptor := LayoutDescriptor{Kind: "taxonomyTerm", Section: "categories"} + l := NewLayoutHandler(false) + + for i := 0; i < b.N; i++ { + layouts := l.For(descriptor, "", HTMLType) + require.NotEmpty(b, layouts) + } } -- cgit v1.2.3