perf: add sync pool for template struct

This commit is contained in:
Jan De Dobbeleer 2024-08-06 08:13:13 +02:00 committed by Jan De Dobbeleer
parent e7cbbde984
commit 84ac954c86
3 changed files with 62 additions and 19 deletions

View file

@ -217,9 +217,8 @@ func (segment *Segment) SetText() {
} }
func (segment *Segment) string() string { func (segment *Segment) string() string {
var templatesResult string
if !segment.Templates.Empty() { if !segment.Templates.Empty() {
templatesResult = segment.Templates.Resolve(segment.writer, segment.env, "", segment.TemplatesLogic) templatesResult := segment.Templates.Resolve(segment.writer, segment.env, "", segment.TemplatesLogic)
if len(segment.Template) == 0 { if len(segment.Template) == 0 {
return templatesResult return templatesResult
} }
@ -233,7 +232,6 @@ func (segment *Segment) string() string {
Template: segment.Template, Template: segment.Template,
Context: segment.writer, Context: segment.writer,
Env: segment.env, Env: segment.env,
TemplatesResult: templatesResult,
} }
text, err := tmpl.Render() text, err := tmpl.Render()

View file

@ -34,10 +34,12 @@ func (l List) Join(context any, env runtime.Environment) string {
if len(l) == 0 { if len(l) == 0 {
return "" return ""
} }
txtTemplate := &Text{ txtTemplate := &Text{
Context: context, Context: context,
Env: env, Env: env,
} }
var buffer strings.Builder var buffer strings.Builder
for _, tmpl := range l { for _, tmpl := range l {
txtTemplate.Template = tmpl txtTemplate.Template = tmpl
@ -45,8 +47,10 @@ func (l List) Join(context any, env runtime.Environment) string {
if err != nil || len(strings.TrimSpace(value)) == 0 { if err != nil || len(strings.TrimSpace(value)) == 0 {
continue continue
} }
buffer.WriteString(value) buffer.WriteString(value)
} }
return buffer.String() return buffer.String()
} }
@ -54,10 +58,12 @@ func (l List) FirstMatch(context any, env runtime.Environment, defaultValue stri
if len(l) == 0 { if len(l) == 0 {
return defaultValue return defaultValue
} }
txtTemplate := &Text{ txtTemplate := &Text{
Context: context, Context: context,
Env: env, Env: env,
} }
for _, tmpl := range l { for _, tmpl := range l {
txtTemplate.Template = tmpl txtTemplate.Template = tmpl
value, err := txtTemplate.Render() value, err := txtTemplate.Render()
@ -66,5 +72,6 @@ func (l List) FirstMatch(context any, env runtime.Environment, defaultValue stri
} }
return value return value
} }
return defaultValue return defaultValue
} }

View file

@ -5,6 +5,7 @@ import (
"errors" "errors"
"reflect" "reflect"
"strings" "strings"
"sync"
"text/template" "text/template"
"github.com/jandedobbeleer/oh-my-posh/src/cache" "github.com/jandedobbeleer/oh-my-posh/src/cache"
@ -50,32 +51,68 @@ var (
shell string shell string
tmplFunc = template.New("cache").Funcs(funcMap()) tmplFunc = template.New("cache").Funcs(funcMap())
contextPool = sync.Pool{
New: func() any {
return &context{}
},
}
buffPool = sync.Pool{
New: func() any {
return &buff{}
},
}
) )
type buff bytes.Buffer
func (b *buff) release() {
(*bytes.Buffer)(b).Reset()
buffPool.Put(b)
}
func (b *buff) Write(p []byte) (n int, err error) {
return (*bytes.Buffer)(b).Write(p)
}
func (b *buff) String() string {
return (*bytes.Buffer)(b).String()
}
type Text struct { type Text struct {
Template string Template string
Context any Context any
Env runtime.Environment Env runtime.Environment
TemplatesResult string
} }
type Data any type Data any
type Context struct { type context struct {
*cache.Template *cache.Template
// Simple container to hold ANY object // Simple container to hold ANY object
Data Data
Templates string initialized bool
} }
func (c *Context) init(t *Text) { func (c *context) init(t *Text) {
c.Data = t.Context c.Data = t.Context
c.Templates = t.TemplatesResult
if tmplCache := t.Env.TemplateCache(); tmplCache != nil { if c.initialized {
c.Template = tmplCache
return return
} }
if tmplCache := t.Env.TemplateCache(); tmplCache != nil {
c.Template = tmplCache
}
c.initialized = true
}
func (c *context) release() {
c.Data = nil
contextPool.Put(c)
} }
func (t *Text) Render() (string, error) { func (t *Text) Render() (string, error) {
@ -95,11 +132,12 @@ func (t *Text) Render() (string, error) {
return "", errors.New(InvalidTemplate) return "", errors.New(InvalidTemplate)
} }
context := &Context{} context := contextPool.Get().(*context)
context.init(t) context.init(t)
defer context.release()
buffer := new(bytes.Buffer) buffer := buffPool.Get().(*buff)
defer buffer.Reset() defer buffer.release()
err = tmpl.Execute(buffer, context) err = tmpl.Execute(buffer, context)
if err != nil { if err != nil {