commit f5ed04bd4a2ba1a62482b381470f04aad98375f5
parent 7730d683e8b030c64c5f986b8166c8e65b777ab3
Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Date: Thu, 16 Nov 2017 01:23:37 +0100
tpl/partials: Fix cache locking
To make sure a cached partial is ony executed exactly once.
Performance same:
```bash
name old time/op new time/op delta
TemplateParamsKeysToLower-4 17.2µs ± 0% 16.5µs ± 0% ~ (p=1.000 n=1+1)
Partial-4 18.6µs ± 0% 19.4µs ± 0% ~ (p=1.000 n=1+1)
PartialCached-4 64.2ns ± 0% 63.7ns ± 0% ~ (p=1.000 n=1+1)
name old alloc/op new alloc/op delta
TemplateParamsKeysToLower-4 2.66kB ± 0% 2.66kB ± 0% ~ (all equal)
Partial-4 1.31kB ± 0% 1.31kB ± 0% ~ (all equal)
PartialCached-4 0.00B 0.00B ~ (all equal)
name old allocs/op new allocs/op delta
TemplateParamsKeysToLower-4 92.0 ± 0% 92.0 ± 0% ~ (all equal)
Partial-4 41.0 ± 0% 41.0 ± 0% ~ (all equal)
```
Diffstat:
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/tpl/partials/partials.go b/tpl/partials/partials.go
@@ -110,27 +110,30 @@ func (ns *Namespace) IncludeCached(name string, context interface{}, variant ...
return ns.getOrCreate(key, name, context)
}
-func (ns *Namespace) getOrCreate(key, name string, context interface{}) (p interface{}, err error) {
- var ok bool
+func (ns *Namespace) getOrCreate(key, name string, context interface{}) (interface{}, error) {
ns.cachedPartials.RLock()
- p, ok = ns.cachedPartials.p[key]
+ p, ok := ns.cachedPartials.p[key]
ns.cachedPartials.RUnlock()
if ok {
- return
+ return p, nil
}
ns.cachedPartials.Lock()
- if p, ok = ns.cachedPartials.p[key]; !ok {
- ns.cachedPartials.Unlock()
- p, err = ns.Include(name, context)
+ defer ns.cachedPartials.Unlock()
- ns.cachedPartials.Lock()
- ns.cachedPartials.p[key] = p
+ // Double-check.
+ if p, ok = ns.cachedPartials.p[key]; ok {
+ return p, nil
+ }
+ p, err := ns.Include(name, context)
+ if err != nil {
+ return nil, err
}
- ns.cachedPartials.Unlock()
- return
+ ns.cachedPartials.p[key] = p
+
+ return p, nil
}