From 344e5abd416cd4c7305cdc2786e9502b56da41c8 Mon Sep 17 00:00:00 2001 From: Joe LeGasse Date: Fri, 11 Mar 2016 13:51:16 -0500 Subject: [PATCH] Changed type-switch a few places to reduce allocations. Slices of tsm1.Value interfaces are only ever used with all the same types, and the previous code would switch on the type returned from a call to Value(), which allocated and returned an interface{} object for the underlying value. This change instead type-switches on the tsm1.Value object itself, allowing it direct access to the underlying value field, eliminating the unecessary allocations. --- tsdb/engine/tsm1/encoding.go | 30 ++++++------ tsdb/engine/tsm1/iterator.gen.go | 32 ++++++------- tsdb/engine/tsm1/iterator.gen.go.tmpl | 8 ++-- tsdb/engine/tsm1/iterator.gen.go.tmpldata | 4 ++ tsdb/engine/tsm1/wal.go | 58 +++++++++++------------ 5 files changed, 68 insertions(+), 64 deletions(-) diff --git a/tsdb/engine/tsm1/encoding.go b/tsdb/engine/tsm1/encoding.go index aac75a2300..cffa53f16f 100644 --- a/tsdb/engine/tsm1/encoding.go +++ b/tsdb/engine/tsm1/encoding.go @@ -85,14 +85,14 @@ func (a Values) Encode(buf []byte) ([]byte, error) { panic("unable to encode block type") } - switch a[0].Value().(type) { - case float64: + switch a[0].(type) { + case *FloatValue: return encodeFloatBlock(buf, a) - case int64: + case *IntegerValue: return encodeIntegerBlock(buf, a) - case bool: + case *BooleanValue: return encodeBooleanBlock(buf, a) - case string: + case *StringValue: return encodeStringBlock(buf, a) } @@ -105,14 +105,14 @@ func (a Values) InfluxQLType() (influxql.DataType, error) { return influxql.Unknown, fmt.Errorf("no values to infer type") } - switch a[0].Value().(type) { - case float64: + switch a[0].(type) { + case *FloatValue: return influxql.Float, nil - case int64: + case *IntegerValue: return influxql.Integer, nil - case bool: + case *BooleanValue: return influxql.Boolean, nil - case string: + case *StringValue: return influxql.String, nil } @@ -237,7 +237,7 @@ func (f *FloatValue) Size() int { } func (f *FloatValue) String() string { - return fmt.Sprintf("%v %v", time.Unix(0, f.unixnano), f.Value()) + return fmt.Sprintf("%v %v", time.Unix(0, f.unixnano), f.value) } func encodeFloatBlock(buf []byte, values []Value) ([]byte, error) { @@ -257,7 +257,7 @@ func encodeFloatBlock(buf []byte, values []Value) ([]byte, error) { for _, v := range values { tsenc.Write(time.Unix(0, v.UnixNano())) - venc.Push(v.Value().(float64)) + venc.Push(v.(*FloatValue).value) } venc.Finish() @@ -384,7 +384,7 @@ func encodeBooleanBlock(buf []byte, values []Value) ([]byte, error) { for _, v := range values { tsenc.Write(time.Unix(0, v.UnixNano())) - venc.Write(v.Value().(bool)) + venc.Write(v.(*BooleanValue).value) } // Encoded timestamp values @@ -496,7 +496,7 @@ func encodeIntegerBlock(buf []byte, values []Value) ([]byte, error) { vEnc := NewIntegerEncoder() for _, v := range values { tsEnc.Write(time.Unix(0, v.UnixNano())) - vEnc.Write(v.Value().(int64)) + vEnc.Write(v.(*IntegerValue).value) } // Encoded timestamp values @@ -607,7 +607,7 @@ func encodeStringBlock(buf []byte, values []Value) ([]byte, error) { vEnc := NewStringEncoder() for _, v := range values { tsEnc.Write(time.Unix(0, v.UnixNano())) - vEnc.Write(v.Value().(string)) + vEnc.Write(v.(*StringValue).value) } // Encoded timestamp values diff --git a/tsdb/engine/tsm1/iterator.gen.go b/tsdb/engine/tsm1/iterator.gen.go index cb639f45f8..bcd78f73ef 100644 --- a/tsdb/engine/tsm1/iterator.gen.go +++ b/tsdb/engine/tsm1/iterator.gen.go @@ -236,7 +236,7 @@ func (c *floatAscendingCursor) peekCache() (t int64, v float64) { } item := c.cache.values[c.cache.pos] - return item.UnixNano(), item.Value().(float64) + return item.UnixNano(), item.(*FloatValue).value } // peekTSM returns the current time/value from tsm. @@ -246,7 +246,7 @@ func (c *floatAscendingCursor) peekTSM() (t int64, v float64) { } item := c.tsm.values[c.tsm.pos] - return item.UnixNano(), item.Value().(float64) + return item.UnixNano(), item.value } // next returns the next key/value for the cursor. @@ -346,7 +346,7 @@ func (c *floatDescendingCursor) peekCache() (t int64, v float64) { } item := c.cache.values[c.cache.pos] - return item.UnixNano(), item.Value().(float64) + return item.UnixNano(), item.(*FloatValue).value } // peekTSM returns the current time/value from tsm. @@ -356,7 +356,7 @@ func (c *floatDescendingCursor) peekTSM() (t int64, v float64) { } item := c.tsm.values[c.tsm.pos] - return item.UnixNano(), item.Value().(float64) + return item.UnixNano(), item.value } // next returns the next key/value for the cursor. @@ -568,7 +568,7 @@ func (c *integerAscendingCursor) peekCache() (t int64, v int64) { } item := c.cache.values[c.cache.pos] - return item.UnixNano(), item.Value().(int64) + return item.UnixNano(), item.(*IntegerValue).value } // peekTSM returns the current time/value from tsm. @@ -578,7 +578,7 @@ func (c *integerAscendingCursor) peekTSM() (t int64, v int64) { } item := c.tsm.values[c.tsm.pos] - return item.UnixNano(), item.Value().(int64) + return item.UnixNano(), item.value } // next returns the next key/value for the cursor. @@ -678,7 +678,7 @@ func (c *integerDescendingCursor) peekCache() (t int64, v int64) { } item := c.cache.values[c.cache.pos] - return item.UnixNano(), item.Value().(int64) + return item.UnixNano(), item.(*IntegerValue).value } // peekTSM returns the current time/value from tsm. @@ -688,7 +688,7 @@ func (c *integerDescendingCursor) peekTSM() (t int64, v int64) { } item := c.tsm.values[c.tsm.pos] - return item.UnixNano(), item.Value().(int64) + return item.UnixNano(), item.value } // next returns the next key/value for the cursor. @@ -900,7 +900,7 @@ func (c *stringAscendingCursor) peekCache() (t int64, v string) { } item := c.cache.values[c.cache.pos] - return item.UnixNano(), item.Value().(string) + return item.UnixNano(), item.(*StringValue).value } // peekTSM returns the current time/value from tsm. @@ -910,7 +910,7 @@ func (c *stringAscendingCursor) peekTSM() (t int64, v string) { } item := c.tsm.values[c.tsm.pos] - return item.UnixNano(), item.Value().(string) + return item.UnixNano(), item.value } // next returns the next key/value for the cursor. @@ -1010,7 +1010,7 @@ func (c *stringDescendingCursor) peekCache() (t int64, v string) { } item := c.cache.values[c.cache.pos] - return item.UnixNano(), item.Value().(string) + return item.UnixNano(), item.(*StringValue).value } // peekTSM returns the current time/value from tsm. @@ -1020,7 +1020,7 @@ func (c *stringDescendingCursor) peekTSM() (t int64, v string) { } item := c.tsm.values[c.tsm.pos] - return item.UnixNano(), item.Value().(string) + return item.UnixNano(), item.value } // next returns the next key/value for the cursor. @@ -1232,7 +1232,7 @@ func (c *booleanAscendingCursor) peekCache() (t int64, v bool) { } item := c.cache.values[c.cache.pos] - return item.UnixNano(), item.Value().(bool) + return item.UnixNano(), item.(*BooleanValue).value } // peekTSM returns the current time/value from tsm. @@ -1242,7 +1242,7 @@ func (c *booleanAscendingCursor) peekTSM() (t int64, v bool) { } item := c.tsm.values[c.tsm.pos] - return item.UnixNano(), item.Value().(bool) + return item.UnixNano(), item.value } // next returns the next key/value for the cursor. @@ -1342,7 +1342,7 @@ func (c *booleanDescendingCursor) peekCache() (t int64, v bool) { } item := c.cache.values[c.cache.pos] - return item.UnixNano(), item.Value().(bool) + return item.UnixNano(), item.(*BooleanValue).value } // peekTSM returns the current time/value from tsm. @@ -1352,7 +1352,7 @@ func (c *booleanDescendingCursor) peekTSM() (t int64, v bool) { } item := c.tsm.values[c.tsm.pos] - return item.UnixNano(), item.Value().(bool) + return item.UnixNano(), item.value } // next returns the next key/value for the cursor. diff --git a/tsdb/engine/tsm1/iterator.gen.go.tmpl b/tsdb/engine/tsm1/iterator.gen.go.tmpl index 030d693795..1b6652c13d 100644 --- a/tsdb/engine/tsm1/iterator.gen.go.tmpl +++ b/tsdb/engine/tsm1/iterator.gen.go.tmpl @@ -232,7 +232,7 @@ func (c *{{.name}}AscendingCursor) peekCache() (t int64, v {{.Type}}) { } item := c.cache.values[c.cache.pos] - return item.UnixNano(), item.Value().({{.Type}}) + return item.UnixNano(), item.({{.ValueType}}).value } // peekTSM returns the current time/value from tsm. @@ -242,7 +242,7 @@ func (c *{{.name}}AscendingCursor) peekTSM() (t int64, v {{.Type}}) { } item := c.tsm.values[c.tsm.pos] - return item.UnixNano(), item.Value().({{.Type}}) + return item.UnixNano(), item.value } // next returns the next key/value for the cursor. @@ -342,7 +342,7 @@ func (c *{{.name}}DescendingCursor) peekCache() (t int64, v {{.Type}}) { } item := c.cache.values[c.cache.pos] - return item.UnixNano(), item.Value().({{.Type}}) + return item.UnixNano(), item.({{.ValueType}}).value } // peekTSM returns the current time/value from tsm. @@ -352,7 +352,7 @@ func (c *{{.name}}DescendingCursor) peekTSM() (t int64, v {{.Type}}) { } item := c.tsm.values[c.tsm.pos] - return item.UnixNano(), item.Value().({{.Type}}) + return item.UnixNano(), item.value } // next returns the next key/value for the cursor. diff --git a/tsdb/engine/tsm1/iterator.gen.go.tmpldata b/tsdb/engine/tsm1/iterator.gen.go.tmpldata index 8d7c5df2ee..4aacad62d8 100644 --- a/tsdb/engine/tsm1/iterator.gen.go.tmpldata +++ b/tsdb/engine/tsm1/iterator.gen.go.tmpldata @@ -3,24 +3,28 @@ "Name":"Float", "name":"float", "Type":"float64", + "ValueType":"*FloatValue", "Nil":"0" }, { "Name":"Integer", "name":"integer", "Type":"int64", + "ValueType":"*IntegerValue", "Nil":"0" }, { "Name":"String", "name":"string", "Type":"string", + "ValueType":"*StringValue", "Nil":"\"\"" }, { "Name":"Boolean", "name":"boolean", "Type":"bool", + "ValueType":"*BooleanValue", "Nil":"false" } ] diff --git a/tsdb/engine/tsm1/wal.go b/tsdb/engine/tsm1/wal.go index 2581b50b26..ead54ba619 100644 --- a/tsdb/engine/tsm1/wal.go +++ b/tsdb/engine/tsm1/wal.go @@ -446,21 +446,21 @@ func (w *WriteWALEntry) Encode(dst []byte) ([]byte, error) { encLen += 8 * len(v) // timestamps (8) - switch v[0].Value().(type) { - case float64, int64: + switch v[0].(type) { + case *FloatValue, *IntegerValue: encLen += 8 * len(v) - case bool: + case *BooleanValue: encLen += 1 * len(v) - case string: + case *StringValue: for _, vv := range v { - str, ok := vv.Value().(string) + str, ok := vv.(*StringValue) if !ok { - return nil, fmt.Errorf("non-string found in string value slice: %T", vv.Value()) + return nil, fmt.Errorf("non-string found in string value slice: %T", vv) } - encLen += 4 + len(str) + encLen += 4 + len(str.value) } default: - return nil, fmt.Errorf("unsupported value type: %T", v[0].Value()) + return nil, fmt.Errorf("unsupported value type: %T", v[0]) } } @@ -476,17 +476,17 @@ func (w *WriteWALEntry) Encode(dst []byte) ([]byte, error) { var curType byte for k, v := range w.Values { - switch v[0].Value().(type) { - case float64: + switch v[0].(type) { + case *FloatValue: curType = float64EntryType - case int64: + case *IntegerValue: curType = integerEntryType - case bool: + case *BooleanValue: curType = booleanEntryType - case string: + case *StringValue: curType = stringEntryType default: - return nil, fmt.Errorf("unsupported value type: %T", v[0].Value()) + return nil, fmt.Errorf("unsupported value type: %T", v[0]) } dst[n] = curType n++ @@ -502,38 +502,38 @@ func (w *WriteWALEntry) Encode(dst []byte) ([]byte, error) { binary.BigEndian.PutUint64(dst[n:n+8], uint64(vv.UnixNano())) n += 8 - switch t := vv.Value().(type) { - case float64: + switch vv := vv.(type) { + case *FloatValue: if curType != float64EntryType { - return nil, fmt.Errorf("incorrect value found in float64 slice: %T", t) + return nil, fmt.Errorf("incorrect value found in %T slice: %T", v[0].Value(), vv) } - binary.BigEndian.PutUint64(dst[n:n+8], math.Float64bits(t)) + binary.BigEndian.PutUint64(dst[n:n+8], math.Float64bits(vv.value)) n += 8 - case int64: + case *IntegerValue: if curType != integerEntryType { - return nil, fmt.Errorf("incorrect value found in int64 slice: %T", t) + return nil, fmt.Errorf("incorrect value found in %T slice: %T", v[0].Value(), vv) } - binary.BigEndian.PutUint64(dst[n:n+8], uint64(t)) + binary.BigEndian.PutUint64(dst[n:n+8], uint64(vv.value)) n += 8 - case bool: + case *BooleanValue: if curType != booleanEntryType { - return nil, fmt.Errorf("incorrect value found in bool slice: %T", t) + return nil, fmt.Errorf("incorrect value found in %T slice: %T", v[0].Value(), vv) } - if t { + if vv.value { dst[n] = 1 } else { dst[n] = 0 } n++ - case string: + case *StringValue: if curType != stringEntryType { - return nil, fmt.Errorf("incorrect value found in string slice: %T", t) + return nil, fmt.Errorf("incorrect value found in %T slice: %T", v[0].Value(), vv) } - binary.BigEndian.PutUint32(dst[n:n+4], uint32(len(t))) + binary.BigEndian.PutUint32(dst[n:n+4], uint32(len(vv.value))) n += 4 - n += copy(dst[n:], t) + n += copy(dst[n:], vv.value) default: - return nil, fmt.Errorf("unsupported value found in value slice: %T", t) + return nil, fmt.Errorf("unsupported value found in %T slice: %T", v[0].Value(), vv) } } }