Skip to content

Commit

Permalink
Merge pull request influxdata#407 from yosiat/alert-perf
Browse files Browse the repository at this point in the history
Buffer pooling in alert templates
  • Loading branch information
Nathaniel Cook committed Apr 4, 2016
2 parents 8f4a98d + 30619b1 commit 8988074
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 8 deletions.
39 changes: 31 additions & 8 deletions alert.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"os"
"os/exec"
"path/filepath"
"sync"
text "text/template"
"time"

Expand Down Expand Up @@ -100,6 +101,8 @@ type AlertNode struct {
idTmpl *text.Template
messageTmpl *text.Template
detailsTmpl *html.Template

bufPool sync.Pool
}

// Create a new AlertNode which caches the most recent item and exposes it over the HTTP API.
Expand All @@ -110,6 +113,13 @@ func newAlertNode(et *ExecutingTask, n *pipeline.AlertNode, l *log.Logger) (an *
}
an.node.runF = an.runAlert

// Create buffer pool for the templates
an.bufPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}

// Parse templates
an.idTmpl, err = text.New("id").Parse(n.Id)
if err != nil {
Expand Down Expand Up @@ -520,8 +530,10 @@ func (a *AlertNode) renderID(name string, group models.GroupID, tags models.Tags
Group: g,
Tags: tags,
}
var id bytes.Buffer
err := a.idTmpl.Execute(&id, info)
id := a.bufPool.Get().(*bytes.Buffer)
defer a.bufPool.Put(id)
id.Reset()
err := a.idTmpl.Execute(id, info)
if err != nil {
return "", err
}
Expand All @@ -545,21 +557,32 @@ func (a *AlertNode) renderMessageAndDetails(id, name string, t time.Time, group
Level: level.String(),
Time: t,
}
var msg bytes.Buffer
err := a.messageTmpl.Execute(&msg, minfo)

// Grab a buffer for the message template and the details template
tmpBuffer := a.bufPool.Get().(*bytes.Buffer)
defer a.bufPool.Put(tmpBuffer)
tmpBuffer.Reset()

err := a.messageTmpl.Execute(tmpBuffer, minfo)
if err != nil {
return "", "", detailsInfo{}, err
}

msg := tmpBuffer.String()
dinfo := detailsInfo{
messageInfo: minfo,
Message: msg.String(),
Message: msg,
}
var details bytes.Buffer
err = a.detailsTmpl.Execute(&details, dinfo)

// Reuse the buffer, for the details template
tmpBuffer.Reset()
err = a.detailsTmpl.Execute(tmpBuffer, dinfo)
if err != nil {
return "", "", dinfo, err
}
return msg.String(), details.String(), dinfo, nil

details := tmpBuffer.String()
return msg, details, dinfo, nil
}

//--------------------------------
Expand Down
28 changes: 28 additions & 0 deletions integrations/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ const (
|count('value')
|log()
`

alertM1Task = `stream
|from()
.measurement('m1')
|alert()
.id('{{ .Name }}_{{ .TaskName }}')
.info(lambda: "value" > 10)
.warn(lambda: "value" > 20)
.crit(lambda: "value" > 30)
`
)

//----------------------------
Expand Down Expand Up @@ -93,6 +103,24 @@ func Benchmark_T1000_P50000_CountTask(b *testing.B) {
Bench(b, 1000, 50000, "dbname", "rpname", "m1", countM1Task)
}

//----------------------------
// Alert Task Benchmarks

// Few tasks, few points
func Benchmark_T10_P500_AlertTask(b *testing.B) {
Bench(b, 10, 500, "dbname", "rpname", "m1", alertM1Task)
}

// Few tasks, many points
func Benchmark_T10_P50000_AlertTask(b *testing.B) {
Bench(b, 10, 50000, "dbname", "rpname", "m1", alertM1Task)
}

// Many tasks, few points
func Benchmark_T1000_P500_AlertTask(b *testing.B) {
Bench(b, 1000, 500, "dbname", "rpname", "m1", alertM1Task)
}

// Generic Benchmark method
func Bench(b *testing.B, tasksCount, pointCount int, db, rp, measurement, tickScript string) {
// Setup HTTPD service
Expand Down

0 comments on commit 8988074

Please sign in to comment.