Skip to content

Commit

Permalink
Precompute cursor keys
Browse files Browse the repository at this point in the history
CPU profiling shows that computing the tagset-based key of each point is significant CPU cost. These keys actually don't change per cursor, so precompute once at mapper-open time, and then use those values as points are drained from the cursor.

Before this change the cursor tag was getting computed on every point, which involved marshalling tags.
  • Loading branch information
otoolep committed Aug 15, 2015
1 parent 34dcead commit 7e72a1a
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 15 deletions.
5 changes: 3 additions & 2 deletions tsdb/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ func (e *Executor) executeRaw(out chan *influxql.Row) {
// Add up to the index to the values
if chunkedOutput == nil {
chunkedOutput = &MapperOutput{
Name: m.bufferedChunk.Name,
Tags: m.bufferedChunk.Tags,
Name: m.bufferedChunk.Name,
Tags: m.bufferedChunk.Tags,
cursorKey: m.bufferedChunk.key(),
}
chunkedOutput.Values = m.bufferedChunk.Values[:ind]
} else {
Expand Down
36 changes: 23 additions & 13 deletions tsdb/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ func (a MapperValues) Less(i, j int) bool { return a[i].Time < a[j].Time }
func (a MapperValues) Swap(i, j int) { a[i], a[j] = a[j], a[i] }

type MapperOutput struct {
Name string `json:"name,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
Fields []string `json:"fields,omitempty"` // Field names of returned data.
Values []*MapperValue `json:"values,omitempty"` // For aggregates contains a single value at [0]
Name string `json:"name,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
Fields []string `json:"fields,omitempty"` // Field names of returned data.
Values []*MapperValue `json:"values,omitempty"` // For aggregates contains a single value at [0]
cursorKey string // Tagset-based key for the source cursor. Cached for performance reasons.
}

func (mo *MapperOutput) key() string {
return formMeasurementTagSetKey(mo.Name, mo.Tags)
return mo.cursorKey
}

// LocalMapper is for retrieving data for a query, from a given shard.
Expand Down Expand Up @@ -287,9 +288,10 @@ func (lm *LocalMapper) nextChunkRaw() (*MapperOutput, error) {

if output == nil {
output = &MapperOutput{
Name: cursor.measurement,
Tags: cursor.tags,
Fields: lm.selectFields,
Name: cursor.measurement,
Tags: cursor.tags,
Fields: lm.selectFields,
cursorKey: cursor.key(),
}
}
value := &MapperValue{Time: k, Value: v, Tags: t}
Expand Down Expand Up @@ -325,10 +327,11 @@ func (lm *LocalMapper) nextChunkAgg() (*MapperOutput, error) {
// for a single tagset.
if output == nil {
output = &MapperOutput{
Name: tsc.measurement,
Tags: tsc.tags,
Fields: lm.selectFields,
Values: make([]*MapperValue, 1),
Name: tsc.measurement,
Tags: tsc.tags,
Fields: lm.selectFields,
Values: make([]*MapperValue, 1),
cursorKey: tsc.key(),
}
// Aggregate values only use the first entry in the Values field. Set the time
// to the start of the interval.
Expand Down Expand Up @@ -643,6 +646,10 @@ type tagSetCursor struct {
// Performance profiling shows that this lookahead needs to be part
// of the tagSetCursor type and not part of the the cursors type.
pointHeap *pointHeap

// Memomize the cursor's tagset-based key. Profiling shows that calculating this
// is significant CPU cost, and it only needs to be done once.
memokey string
}

// tagSetCursors represents a sortable slice of tagSetCursors.
Expand Down Expand Up @@ -675,7 +682,10 @@ func newTagSetCursor(m string, t map[string]string, c []*seriesCursor, d *FieldC
}

func (tsc *tagSetCursor) key() string {
return formMeasurementTagSetKey(tsc.measurement, tsc.tags)
if tsc.memokey == "" {
tsc.memokey = formMeasurementTagSetKey(tsc.measurement, tsc.tags)
}
return tsc.memokey
}

// Next returns the next matching series-key, timestamp byte slice and meta tags for the tagset. Filtering
Expand Down

0 comments on commit 7e72a1a

Please sign in to comment.