Merge pull request #8652 from influxdata/sgc-literal-cursor
Reduce allocations using nil cursors and literal value cursorspull/8655/merge
commit
5449285c4c
|
@ -12,6 +12,7 @@
|
|||
- [#8426](https://github.com/influxdata/influxdb/issues/8426): Add `parse-multivalue-plugin` to allow users to choose how multivalue plugins should be handled by the collectd service.
|
||||
- [#8548](https://github.com/influxdata/influxdb/issues/8548): Allow panic recovery to be disabled when investigating server issues.
|
||||
- [#8525](https://github.com/influxdata/influxdb/issues/8525): Support http pipelining for /query endpoint.
|
||||
- [#8652](https://github.com/influxdata/influxdb/pull/8652): Reduce allocations when reading data
|
||||
|
||||
### Bugfixes
|
||||
|
||||
|
|
|
@ -1852,19 +1852,19 @@ func (e *Engine) createVarRefSeriesIterator(ref *influxql.VarRef, name string, s
|
|||
// If a field was requested, use a nil cursor of the requested type.
|
||||
switch ref.Type {
|
||||
case influxql.Float, influxql.AnyField:
|
||||
aux[i] = &floatNilLiteralCursor{}
|
||||
aux[i] = nilFloatLiteralValueCursor
|
||||
continue
|
||||
case influxql.Integer:
|
||||
aux[i] = &integerNilLiteralCursor{}
|
||||
aux[i] = nilIntegerLiteralValueCursor
|
||||
continue
|
||||
case influxql.Unsigned:
|
||||
aux[i] = &unsignedNilLiteralCursor{}
|
||||
aux[i] = nilUnsignedLiteralValueCursor
|
||||
continue
|
||||
case influxql.String:
|
||||
aux[i] = &stringNilLiteralCursor{}
|
||||
aux[i] = nilStringLiteralValueCursor
|
||||
continue
|
||||
case influxql.Boolean:
|
||||
aux[i] = &booleanNilLiteralCursor{}
|
||||
aux[i] = nilBooleanLiteralValueCursor
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -1872,9 +1872,9 @@ func (e *Engine) createVarRefSeriesIterator(ref *influxql.VarRef, name string, s
|
|||
// If field doesn't exist, use the tag value.
|
||||
if v := tags.Value(ref.Val); v == "" {
|
||||
// However, if the tag value is blank then return a null.
|
||||
aux[i] = &stringNilLiteralCursor{}
|
||||
aux[i] = nilStringLiteralValueCursor
|
||||
} else {
|
||||
aux[i] = &stringLiteralCursor{value: v}
|
||||
aux[i] = &literalValueCursor{value: v}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1896,19 +1896,19 @@ func (e *Engine) createVarRefSeriesIterator(ref *influxql.VarRef, name string, s
|
|||
// If a field was requested, use a nil cursor of the requested type.
|
||||
switch ref.Type {
|
||||
case influxql.Float, influxql.AnyField:
|
||||
conds[i] = &floatNilLiteralCursor{}
|
||||
conds[i] = nilFloatLiteralValueCursor
|
||||
continue
|
||||
case influxql.Integer:
|
||||
conds[i] = &integerNilLiteralCursor{}
|
||||
conds[i] = nilIntegerLiteralValueCursor
|
||||
continue
|
||||
case influxql.Unsigned:
|
||||
conds[i] = &unsignedNilLiteralCursor{}
|
||||
conds[i] = nilUnsignedLiteralValueCursor
|
||||
continue
|
||||
case influxql.String:
|
||||
conds[i] = &stringNilLiteralCursor{}
|
||||
conds[i] = nilStringLiteralValueCursor
|
||||
continue
|
||||
case influxql.Boolean:
|
||||
conds[i] = &booleanNilLiteralCursor{}
|
||||
conds[i] = nilBooleanLiteralValueCursor
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -1916,9 +1916,9 @@ func (e *Engine) createVarRefSeriesIterator(ref *influxql.VarRef, name string, s
|
|||
// If field doesn't exist, use the tag value.
|
||||
if v := tags.Value(ref.Val); v == "" {
|
||||
// However, if the tag value is blank then return a null.
|
||||
conds[i] = &stringNilLiteralCursor{}
|
||||
conds[i] = nilStringLiteralValueCursor
|
||||
} else {
|
||||
conds[i] = &stringLiteralCursor{value: v}
|
||||
conds[i] = &literalValueCursor{value: v}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -532,26 +532,6 @@ func (c *floatDescendingCursor) nextTSM() {
|
|||
}
|
||||
}
|
||||
|
||||
// floatLiteralCursor represents a cursor that always returns a single value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type floatLiteralCursor struct {
|
||||
value float64
|
||||
}
|
||||
|
||||
func (c *floatLiteralCursor) close() error { return nil }
|
||||
func (c *floatLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *floatLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *floatLiteralCursor) nextAt(seek int64) interface{} { return c.value }
|
||||
|
||||
// floatNilLiteralCursor represents a cursor that always returns a typed nil value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type floatNilLiteralCursor struct{}
|
||||
|
||||
func (c *floatNilLiteralCursor) close() error { return nil }
|
||||
func (c *floatNilLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, (*float64)(nil) }
|
||||
func (c *floatNilLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, (*float64)(nil) }
|
||||
func (c *floatNilLiteralCursor) nextAt(seek int64) interface{} { return (*float64)(nil) }
|
||||
|
||||
type integerIterator struct {
|
||||
cur integerCursor
|
||||
aux []cursorAt
|
||||
|
@ -967,26 +947,6 @@ func (c *integerDescendingCursor) nextTSM() {
|
|||
}
|
||||
}
|
||||
|
||||
// integerLiteralCursor represents a cursor that always returns a single value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type integerLiteralCursor struct {
|
||||
value int64
|
||||
}
|
||||
|
||||
func (c *integerLiteralCursor) close() error { return nil }
|
||||
func (c *integerLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *integerLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *integerLiteralCursor) nextAt(seek int64) interface{} { return c.value }
|
||||
|
||||
// integerNilLiteralCursor represents a cursor that always returns a typed nil value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type integerNilLiteralCursor struct{}
|
||||
|
||||
func (c *integerNilLiteralCursor) close() error { return nil }
|
||||
func (c *integerNilLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, (*int64)(nil) }
|
||||
func (c *integerNilLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, (*int64)(nil) }
|
||||
func (c *integerNilLiteralCursor) nextAt(seek int64) interface{} { return (*int64)(nil) }
|
||||
|
||||
type unsignedIterator struct {
|
||||
cur unsignedCursor
|
||||
aux []cursorAt
|
||||
|
@ -1402,26 +1362,6 @@ func (c *unsignedDescendingCursor) nextTSM() {
|
|||
}
|
||||
}
|
||||
|
||||
// unsignedLiteralCursor represents a cursor that always returns a single value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type unsignedLiteralCursor struct {
|
||||
value uint64
|
||||
}
|
||||
|
||||
func (c *unsignedLiteralCursor) close() error { return nil }
|
||||
func (c *unsignedLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *unsignedLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *unsignedLiteralCursor) nextAt(seek int64) interface{} { return c.value }
|
||||
|
||||
// unsignedNilLiteralCursor represents a cursor that always returns a typed nil value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type unsignedNilLiteralCursor struct{}
|
||||
|
||||
func (c *unsignedNilLiteralCursor) close() error { return nil }
|
||||
func (c *unsignedNilLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, (*uint64)(nil) }
|
||||
func (c *unsignedNilLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, (*uint64)(nil) }
|
||||
func (c *unsignedNilLiteralCursor) nextAt(seek int64) interface{} { return (*uint64)(nil) }
|
||||
|
||||
type stringIterator struct {
|
||||
cur stringCursor
|
||||
aux []cursorAt
|
||||
|
@ -1837,26 +1777,6 @@ func (c *stringDescendingCursor) nextTSM() {
|
|||
}
|
||||
}
|
||||
|
||||
// stringLiteralCursor represents a cursor that always returns a single value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type stringLiteralCursor struct {
|
||||
value string
|
||||
}
|
||||
|
||||
func (c *stringLiteralCursor) close() error { return nil }
|
||||
func (c *stringLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *stringLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *stringLiteralCursor) nextAt(seek int64) interface{} { return c.value }
|
||||
|
||||
// stringNilLiteralCursor represents a cursor that always returns a typed nil value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type stringNilLiteralCursor struct{}
|
||||
|
||||
func (c *stringNilLiteralCursor) close() error { return nil }
|
||||
func (c *stringNilLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, (*string)(nil) }
|
||||
func (c *stringNilLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, (*string)(nil) }
|
||||
func (c *stringNilLiteralCursor) nextAt(seek int64) interface{} { return (*string)(nil) }
|
||||
|
||||
type booleanIterator struct {
|
||||
cur booleanCursor
|
||||
aux []cursorAt
|
||||
|
@ -2272,24 +2192,4 @@ func (c *booleanDescendingCursor) nextTSM() {
|
|||
}
|
||||
}
|
||||
|
||||
// booleanLiteralCursor represents a cursor that always returns a single value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type booleanLiteralCursor struct {
|
||||
value bool
|
||||
}
|
||||
|
||||
func (c *booleanLiteralCursor) close() error { return nil }
|
||||
func (c *booleanLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *booleanLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *booleanLiteralCursor) nextAt(seek int64) interface{} { return c.value }
|
||||
|
||||
// booleanNilLiteralCursor represents a cursor that always returns a typed nil value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type booleanNilLiteralCursor struct{}
|
||||
|
||||
func (c *booleanNilLiteralCursor) close() error { return nil }
|
||||
func (c *booleanNilLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, (*bool)(nil) }
|
||||
func (c *booleanNilLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, (*bool)(nil) }
|
||||
func (c *booleanNilLiteralCursor) nextAt(seek int64) interface{} { return (*bool)(nil) }
|
||||
|
||||
var _ = fmt.Print
|
||||
|
|
|
@ -528,27 +528,6 @@ func (c *{{.name}}DescendingCursor) nextTSM() {
|
|||
}
|
||||
}
|
||||
|
||||
// {{.name}}LiteralCursor represents a cursor that always returns a single value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type {{.name}}LiteralCursor struct {
|
||||
value {{.Type}}
|
||||
}
|
||||
|
||||
func (c *{{.name}}LiteralCursor) close() error { return nil }
|
||||
func (c *{{.name}}LiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *{{.name}}LiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *{{.name}}LiteralCursor) nextAt(seek int64) interface{} { return c.value }
|
||||
|
||||
|
||||
// {{.name}}NilLiteralCursor represents a cursor that always returns a typed nil value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type {{.name}}NilLiteralCursor struct {}
|
||||
|
||||
func (c *{{.name}}NilLiteralCursor) close() error { return nil }
|
||||
func (c *{{.name}}NilLiteralCursor) peek() (t int64, v interface{}) { return tsdb.EOF, (*{{.Type}})(nil) }
|
||||
func (c *{{.name}}NilLiteralCursor) next() (t int64, v interface{}) { return tsdb.EOF, (*{{.Type}})(nil) }
|
||||
func (c *{{.name}}NilLiteralCursor) nextAt(seek int64) interface{} { return (*{{.Type}})(nil) }
|
||||
|
||||
{{end}}
|
||||
|
||||
var _ = fmt.Print
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package tsm1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/influxdb/influxql"
|
||||
)
|
||||
|
||||
func BenchmarkIntegerIterator_Next(b *testing.B) {
|
||||
opt := influxql.IteratorOptions{
|
||||
Aux: []influxql.VarRef{{Val: "f1"}, {Val: "f1"}, {Val: "f1"}, {Val: "f1"}},
|
||||
}
|
||||
aux := []cursorAt{
|
||||
&literalValueCursor{value: "foo bar"},
|
||||
&literalValueCursor{value: int64(1e3)},
|
||||
&literalValueCursor{value: float64(1e3)},
|
||||
&literalValueCursor{value: true},
|
||||
}
|
||||
|
||||
cur := newIntegerIterator("m0", influxql.Tags{}, opt, &infiniteIntegerCursor{}, aux, nil, nil)
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
cur.Next()
|
||||
}
|
||||
}
|
||||
|
||||
type infiniteIntegerCursor struct{}
|
||||
|
||||
func (*infiniteIntegerCursor) close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*infiniteIntegerCursor) next() (t int64, v interface{}) {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
func (*infiniteIntegerCursor) nextInteger() (t int64, v int64) {
|
||||
return 0, 0
|
||||
}
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/influxdata/influxdb/influxql"
|
||||
"github.com/influxdata/influxdb/tsdb"
|
||||
)
|
||||
|
||||
func newLimitIterator(input influxql.Iterator, opt influxql.IteratorOptions) influxql.Iterator {
|
||||
|
@ -100,3 +101,23 @@ func (c *unsignedCastIntegerCursor) nextUnsigned() (int64, uint64) {
|
|||
t, v := c.cursor.nextInteger()
|
||||
return t, uint64(v)
|
||||
}
|
||||
|
||||
// literalValueCursor represents a cursor that always returns a single value.
|
||||
// It doesn't not have a time value so it can only be used with nextAt().
|
||||
type literalValueCursor struct {
|
||||
value interface{}
|
||||
}
|
||||
|
||||
func (c *literalValueCursor) close() error { return nil }
|
||||
func (c *literalValueCursor) peek() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *literalValueCursor) next() (t int64, v interface{}) { return tsdb.EOF, c.value }
|
||||
func (c *literalValueCursor) nextAt(seek int64) interface{} { return c.value }
|
||||
|
||||
// preallocate and cast to cursorAt to avoid allocations
|
||||
var (
|
||||
nilFloatLiteralValueCursor cursorAt = &literalValueCursor{value: (*float64)(nil)}
|
||||
nilIntegerLiteralValueCursor cursorAt = &literalValueCursor{value: (*int64)(nil)}
|
||||
nilUnsignedLiteralValueCursor cursorAt = &literalValueCursor{value: (*uint64)(nil)}
|
||||
nilStringLiteralValueCursor cursorAt = &literalValueCursor{value: (*string)(nil)}
|
||||
nilBooleanLiteralValueCursor cursorAt = &literalValueCursor{value: (*bool)(nil)}
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue