reuse ValuerEval objects
Scanner objects and iterators often need a ValuerEval. This object is created, often with a function call, and has at least one interface in it, so it allocates storage. Then it's dropped again right away. The only part of it that might be subject to change is usually a map. While the map's contents change over time, the actual map doesn't change for the lifetime of the object. So, in both iterators and scanners, stash the ValuerEval and continue reusing it. On a query returning a fair number of data points, this produces a small (<5% in practice) improvement in observed performance, visible as a significant reduction in time spent in runtime (mallocgc, newobject, etcetera). The performance improvement isn't big, but it's reasonably easy to evaluate it and establish that it's a safe change to make. Signed-off-by: seebs <seebs@seebs.net>pull/10414/head
parent
59e4d86cbf
commit
5525240de3
|
@ -144,7 +144,8 @@ type scannerCursorBase struct {
|
|||
columns []influxql.VarRef
|
||||
loc *time.Location
|
||||
|
||||
scan scannerFunc
|
||||
scan scannerFunc
|
||||
valuer influxql.ValuerEval
|
||||
}
|
||||
|
||||
func newScannerCursorBase(scan scannerFunc, fields []*influxql.Field, loc *time.Location) scannerCursorBase {
|
||||
|
@ -162,12 +163,20 @@ func newScannerCursorBase(scan scannerFunc, fields []*influxql.Field, loc *time.
|
|||
loc = time.UTC
|
||||
}
|
||||
|
||||
m := make(map[string]interface{})
|
||||
return scannerCursorBase{
|
||||
fields: exprs,
|
||||
m: make(map[string]interface{}),
|
||||
m: m,
|
||||
columns: columns,
|
||||
loc: loc,
|
||||
scan: scan,
|
||||
valuer: influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
MathValuer{},
|
||||
influxql.MapValuer(m),
|
||||
),
|
||||
IntegerFloatDivision: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,20 +198,13 @@ func (cur *scannerCursorBase) Scan(row *Row) bool {
|
|||
row.Values = make([]interface{}, len(cur.columns))
|
||||
}
|
||||
|
||||
valuer := influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
MathValuer{},
|
||||
influxql.MapValuer(cur.m),
|
||||
),
|
||||
IntegerFloatDivision: true,
|
||||
}
|
||||
for i, expr := range cur.fields {
|
||||
// A special case if the field is time to reduce memory allocations.
|
||||
if ref, ok := expr.(*influxql.VarRef); ok && ref.Val == "time" {
|
||||
row.Values[i] = time.Unix(0, row.Time).In(cur.loc)
|
||||
continue
|
||||
}
|
||||
v := valuer.Eval(expr)
|
||||
v := cur.valuer.Eval(expr)
|
||||
if fv, ok := v.(float64); ok && math.IsNaN(fv) {
|
||||
// If the float value is NaN, convert it to a null float
|
||||
// so this can be serialized correctly, but not mistaken for
|
||||
|
@ -339,6 +341,7 @@ type filterCursor struct {
|
|||
fields map[string]IteratorMap
|
||||
filter influxql.Expr
|
||||
m map[string]interface{}
|
||||
valuer influxql.ValuerEval
|
||||
}
|
||||
|
||||
func newFilterCursor(cur Cursor, filter influxql.Expr) *filterCursor {
|
||||
|
@ -362,11 +365,13 @@ func newFilterCursor(cur Cursor, filter influxql.Expr) *filterCursor {
|
|||
fields[name.Val] = TagMap(name.Val)
|
||||
}
|
||||
}
|
||||
m := make(map[string]interface{})
|
||||
return &filterCursor{
|
||||
Cursor: cur,
|
||||
fields: fields,
|
||||
filter: filter,
|
||||
m: make(map[string]interface{}),
|
||||
m: m,
|
||||
valuer: influxql.ValuerEval{Valuer: influxql.MapValuer(m)},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,10 +382,7 @@ func (cur *filterCursor) Scan(row *Row) bool {
|
|||
cur.m[name] = f.Value(row)
|
||||
}
|
||||
|
||||
valuer := influxql.ValuerEval{
|
||||
Valuer: influxql.MapValuer(cur.m),
|
||||
}
|
||||
if valuer.EvalBool(cur.filter) {
|
||||
if cur.valuer.EvalBool(cur.filter) {
|
||||
// Passes the filter! Return true. We no longer need to
|
||||
// search for a suitable value.
|
||||
return true
|
||||
|
|
|
@ -196,6 +196,7 @@ type floatIterator struct {
|
|||
statsLock sync.Mutex
|
||||
stats query.IteratorStats
|
||||
statsBuf query.IteratorStats
|
||||
valuer influxql.ValuerEval
|
||||
}
|
||||
|
||||
func newFloatIterator(name string, tags query.Tags, opt query.IteratorOptions, cur floatCursor, aux []cursorAt, conds []cursorAt, condNames []string) *floatIterator {
|
||||
|
@ -223,6 +224,13 @@ func newFloatIterator(name string, tags query.Tags, opt query.IteratorOptions, c
|
|||
itr.conds.names = condNames
|
||||
itr.conds.curs = conds
|
||||
|
||||
itr.valuer = influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
|
||||
return itr
|
||||
}
|
||||
|
||||
|
@ -270,13 +278,7 @@ func (itr *floatIterator) Next() (*query.FloatPoint, error) {
|
|||
}
|
||||
|
||||
// Evaluate condition, if one exists. Retry if it fails.
|
||||
valuer := influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
if itr.opt.Condition != nil && !valuer.EvalBool(itr.opt.Condition) {
|
||||
if itr.opt.Condition != nil && !itr.valuer.EvalBool(itr.opt.Condition) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -674,6 +676,7 @@ type integerIterator struct {
|
|||
statsLock sync.Mutex
|
||||
stats query.IteratorStats
|
||||
statsBuf query.IteratorStats
|
||||
valuer influxql.ValuerEval
|
||||
}
|
||||
|
||||
func newIntegerIterator(name string, tags query.Tags, opt query.IteratorOptions, cur integerCursor, aux []cursorAt, conds []cursorAt, condNames []string) *integerIterator {
|
||||
|
@ -701,6 +704,13 @@ func newIntegerIterator(name string, tags query.Tags, opt query.IteratorOptions,
|
|||
itr.conds.names = condNames
|
||||
itr.conds.curs = conds
|
||||
|
||||
itr.valuer = influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
|
||||
return itr
|
||||
}
|
||||
|
||||
|
@ -748,13 +758,7 @@ func (itr *integerIterator) Next() (*query.IntegerPoint, error) {
|
|||
}
|
||||
|
||||
// Evaluate condition, if one exists. Retry if it fails.
|
||||
valuer := influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
if itr.opt.Condition != nil && !valuer.EvalBool(itr.opt.Condition) {
|
||||
if itr.opt.Condition != nil && !itr.valuer.EvalBool(itr.opt.Condition) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -1152,6 +1156,7 @@ type unsignedIterator struct {
|
|||
statsLock sync.Mutex
|
||||
stats query.IteratorStats
|
||||
statsBuf query.IteratorStats
|
||||
valuer influxql.ValuerEval
|
||||
}
|
||||
|
||||
func newUnsignedIterator(name string, tags query.Tags, opt query.IteratorOptions, cur unsignedCursor, aux []cursorAt, conds []cursorAt, condNames []string) *unsignedIterator {
|
||||
|
@ -1179,6 +1184,13 @@ func newUnsignedIterator(name string, tags query.Tags, opt query.IteratorOptions
|
|||
itr.conds.names = condNames
|
||||
itr.conds.curs = conds
|
||||
|
||||
itr.valuer = influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
|
||||
return itr
|
||||
}
|
||||
|
||||
|
@ -1226,13 +1238,7 @@ func (itr *unsignedIterator) Next() (*query.UnsignedPoint, error) {
|
|||
}
|
||||
|
||||
// Evaluate condition, if one exists. Retry if it fails.
|
||||
valuer := influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
if itr.opt.Condition != nil && !valuer.EvalBool(itr.opt.Condition) {
|
||||
if itr.opt.Condition != nil && !itr.valuer.EvalBool(itr.opt.Condition) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -1630,6 +1636,7 @@ type stringIterator struct {
|
|||
statsLock sync.Mutex
|
||||
stats query.IteratorStats
|
||||
statsBuf query.IteratorStats
|
||||
valuer influxql.ValuerEval
|
||||
}
|
||||
|
||||
func newStringIterator(name string, tags query.Tags, opt query.IteratorOptions, cur stringCursor, aux []cursorAt, conds []cursorAt, condNames []string) *stringIterator {
|
||||
|
@ -1657,6 +1664,13 @@ func newStringIterator(name string, tags query.Tags, opt query.IteratorOptions,
|
|||
itr.conds.names = condNames
|
||||
itr.conds.curs = conds
|
||||
|
||||
itr.valuer = influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
|
||||
return itr
|
||||
}
|
||||
|
||||
|
@ -1704,13 +1718,7 @@ func (itr *stringIterator) Next() (*query.StringPoint, error) {
|
|||
}
|
||||
|
||||
// Evaluate condition, if one exists. Retry if it fails.
|
||||
valuer := influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
if itr.opt.Condition != nil && !valuer.EvalBool(itr.opt.Condition) {
|
||||
if itr.opt.Condition != nil && !itr.valuer.EvalBool(itr.opt.Condition) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -2108,6 +2116,7 @@ type booleanIterator struct {
|
|||
statsLock sync.Mutex
|
||||
stats query.IteratorStats
|
||||
statsBuf query.IteratorStats
|
||||
valuer influxql.ValuerEval
|
||||
}
|
||||
|
||||
func newBooleanIterator(name string, tags query.Tags, opt query.IteratorOptions, cur booleanCursor, aux []cursorAt, conds []cursorAt, condNames []string) *booleanIterator {
|
||||
|
@ -2135,6 +2144,13 @@ func newBooleanIterator(name string, tags query.Tags, opt query.IteratorOptions,
|
|||
itr.conds.names = condNames
|
||||
itr.conds.curs = conds
|
||||
|
||||
itr.valuer = influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
|
||||
return itr
|
||||
}
|
||||
|
||||
|
@ -2182,13 +2198,7 @@ func (itr *booleanIterator) Next() (*query.BooleanPoint, error) {
|
|||
}
|
||||
|
||||
// Evaluate condition, if one exists. Retry if it fails.
|
||||
valuer := influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
if itr.opt.Condition != nil && !valuer.EvalBool(itr.opt.Condition) {
|
||||
if itr.opt.Condition != nil && !itr.valuer.EvalBool(itr.opt.Condition) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -194,6 +194,7 @@ type {{.name}}Iterator struct {
|
|||
statsLock sync.Mutex
|
||||
stats query.IteratorStats
|
||||
statsBuf query.IteratorStats
|
||||
valuer influxql.ValuerEval
|
||||
}
|
||||
|
||||
func new{{.Name}}Iterator(name string, tags query.Tags, opt query.IteratorOptions, cur {{.name}}Cursor, aux []cursorAt, conds []cursorAt, condNames []string) *{{.name}}Iterator {
|
||||
|
@ -221,6 +222,13 @@ func new{{.Name}}Iterator(name string, tags query.Tags, opt query.IteratorOption
|
|||
itr.conds.names = condNames
|
||||
itr.conds.curs = conds
|
||||
|
||||
itr.valuer = influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
|
||||
return itr
|
||||
}
|
||||
|
||||
|
@ -268,13 +276,7 @@ func (itr *{{.name}}Iterator) Next() (*query.{{.Name}}Point, error) {
|
|||
}
|
||||
|
||||
// Evaluate condition, if one exists. Retry if it fails.
|
||||
valuer := influxql.ValuerEval{
|
||||
Valuer: influxql.MultiValuer(
|
||||
query.MathValuer{},
|
||||
influxql.MapValuer(itr.m),
|
||||
),
|
||||
}
|
||||
if itr.opt.Condition != nil && !valuer.EvalBool(itr.opt.Condition) {
|
||||
if itr.opt.Condition != nil && !itr.valuer.EvalBool(itr.opt.Condition) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue