From 3de04685f854d74afad1dd258832f7cd3ba8d556 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Mon, 25 Dec 2017 10:00:01 +0000 Subject: [PATCH] optimisation: pre-allocate, and fewer slices during summarisation Pre-allocating slices really pays dividends when we create loads of them and they don't grow very large. We take special care to return nil rather than 0-length slices. This a) saves further on allocation, and b) is required for some crude tests to pass that match on nil rather than length. Also, a bunch of code in templates/tables used slices as Maybe's, i.e. returning nil or a single-element slice, which is horrendously inefficient. Eliminating these saves a lot of allocations. --- render/detailed/parents.go | 9 ++++++++- report/metadata_template.go | 22 +++++++++++++++------- report/metric_template.go | 20 ++++++++++++++------ report/table.go | 5 ++++- 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/render/detailed/parents.go b/render/detailed/parents.go index 0692c39fa5..e7fa2ccca8 100644 --- a/render/detailed/parents.go +++ b/render/detailed/parents.go @@ -38,7 +38,11 @@ var ( // Parents renders the parents of this report.Node, which have been aggregated // from the probe reports. -func Parents(r report.Report, n report.Node) (result []Parent) { +func Parents(r report.Report, n report.Node) []Parent { + if n.Parents.Size() == 0 { + return nil + } + result := make([]Parent, 0, n.Parents.Size()) topologyIDs := []string{} for topologyID := range getLabelForTopology { topologyIDs = append(topologyIDs, topologyID) @@ -80,6 +84,9 @@ func Parents(r report.Report, n report.Node) (result []Parent) { }) } } + if len(result) == 0 { + return nil + } return result } diff --git a/report/metadata_template.go b/report/metadata_template.go index 1bee5e642c..152b788d5e 100644 --- a/report/metadata_template.go +++ b/report/metadata_template.go @@ -28,8 +28,8 @@ type MetadataTemplate struct { From string `json:"from,omitempty"` // Defines how to get the value from a report node } -// MetadataRows returns the rows for a node -func (t MetadataTemplate) MetadataRows(n Node) []MetadataRow { +// MetadataRow returns the row for a node +func (t MetadataTemplate) MetadataRow(n Node) (MetadataRow, bool) { from := fromDefault switch t.From { case FromLatest: @@ -40,16 +40,16 @@ func (t MetadataTemplate) MetadataRows(n Node) []MetadataRow { from = fromCounters } if val, ok := from(n, t.ID); ok { - return []MetadataRow{{ + return MetadataRow{ ID: t.ID, Label: t.Label, Value: val, Truncate: t.Truncate, Datatype: t.Datatype, Priority: t.Priority, - }} + }, true } - return nil + return MetadataRow{}, false } func fromDefault(n Node, key string) (string, bool) { @@ -90,9 +90,17 @@ type MetadataTemplates map[string]MetadataTemplate // MetadataRows returns the rows for a node func (e MetadataTemplates) MetadataRows(n Node) []MetadataRow { - var rows []MetadataRow + if len(e) == 0 { + return nil + } + rows := make([]MetadataRow, 0, len(e)) for _, template := range e { - rows = append(rows, template.MetadataRows(n)...) + if row, ok := template.MetadataRow(n); ok { + rows = append(rows, row) + } + } + if len(rows) == 0 { + return nil } sort.Sort(MetadataRowsByPriority(rows)) return rows diff --git a/report/metric_template.go b/report/metric_template.go index 9e2d441f02..c5d67e0d7f 100644 --- a/report/metric_template.go +++ b/report/metric_template.go @@ -14,11 +14,11 @@ type MetricTemplate struct { Priority float64 `json:"priority,omitempty"` } -// MetricRows returns the rows for a node -func (t MetricTemplate) MetricRows(n Node) []MetricRow { +// MetricRow returns the row for a node +func (t MetricTemplate) MetricRow(n Node) (MetricRow, bool) { metric, ok := n.Metrics.Lookup(t.ID) if !ok { - return nil + return MetricRow{}, false } row := MetricRow{ ID: t.ID, @@ -31,7 +31,7 @@ func (t MetricTemplate) MetricRows(n Node) []MetricRow { if s, ok := metric.LastSample(); ok { row.Value = toFixed(s.Value, 2) } - return []MetricRow{row} + return row, true } // MetricTemplates is a mergeable set of metric templates @@ -39,9 +39,17 @@ type MetricTemplates map[string]MetricTemplate // MetricRows returns the rows for a node func (e MetricTemplates) MetricRows(n Node) []MetricRow { - var rows []MetricRow + if len(e) == 0 { + return nil + } + rows := make([]MetricRow, 0, len(e)) for _, template := range e { - rows = append(rows, template.MetricRows(n)...) + if row, ok := template.MetricRow(n); ok { + rows = append(rows, row) + } + } + if len(rows) == 0 { + return nil } sort.Sort(MetricRowsByPriority(rows)) return rows diff --git a/report/table.go b/report/table.go index 859a8c1f17..9e116d43b6 100644 --- a/report/table.go +++ b/report/table.go @@ -252,7 +252,10 @@ type TableTemplates map[string]TableTemplate // Tables renders the TableTemplates for a given node. func (t TableTemplates) Tables(node Node) []Table { - var result []Table + if len(t) == 0 { + return nil + } + result := make([]Table, 0, len(t)) for _, template := range t { rows, truncationCount := node.ExtractTable(template) // Extract the type from the template; default to