Browse Source

Speed up proto postprocessing phase in proto decoder

The proto decoder associates creates pointers to reference each
location/function/mapping based on their id. These ids can be
arbitrary uint64s, but often they are generated in sequence from
1 to N.

The overhead of keeping these indices in a hash is about a 20% of
the cost of decoding a profile. Speed it up by using an array to
track values from 1 to N, and a hash for values outside that range.
Raul Silvera 8 years ago
parent
commit
74a2f64500
1 changed files with 34 additions and 11 deletions
  1. 34
    11
      profile/encode.go

+ 34
- 11
profile/encode.go View File

16
 
16
 
17
 import (
17
 import (
18
 	"errors"
18
 	"errors"
19
-	"fmt"
20
 	"sort"
19
 	"sort"
21
 )
20
 )
22
 
21
 
231
 // The unexported fields are cleared up to facilitate testing.
230
 // The unexported fields are cleared up to facilitate testing.
232
 func (p *Profile) postDecode() error {
231
 func (p *Profile) postDecode() error {
233
 	var err error
232
 	var err error
234
-	mappings := make(map[uint64]*Mapping)
233
+	mappings := make(map[uint64]*Mapping, len(p.Mapping))
234
+	mappingIds := make([]*Mapping, len(p.Mapping)+1)
235
 	for _, m := range p.Mapping {
235
 	for _, m := range p.Mapping {
236
 		m.File, err = getString(p.stringTable, &m.fileX, err)
236
 		m.File, err = getString(p.stringTable, &m.fileX, err)
237
 		m.BuildID, err = getString(p.stringTable, &m.buildIDX, err)
237
 		m.BuildID, err = getString(p.stringTable, &m.buildIDX, err)
238
+		if m.ID < uint64(len(mappingIds)) {
239
+			mappingIds[m.ID] = m
240
+			continue
241
+		}
238
 		mappings[m.ID] = m
242
 		mappings[m.ID] = m
239
 	}
243
 	}
240
 
244
 
241
-	functions := make(map[uint64]*Function)
245
+	functions := make(map[uint64]*Function, len(p.Function))
246
+	functionIds := make([]*Function, len(p.Function)+1)
242
 	for _, f := range p.Function {
247
 	for _, f := range p.Function {
243
 		f.Name, err = getString(p.stringTable, &f.nameX, err)
248
 		f.Name, err = getString(p.stringTable, &f.nameX, err)
244
 		f.SystemName, err = getString(p.stringTable, &f.systemNameX, err)
249
 		f.SystemName, err = getString(p.stringTable, &f.systemNameX, err)
245
 		f.Filename, err = getString(p.stringTable, &f.filenameX, err)
250
 		f.Filename, err = getString(p.stringTable, &f.filenameX, err)
251
+		if f.ID < uint64(len(functionIds)) {
252
+			functionIds[f.ID] = f
253
+			continue
254
+		}
246
 		functions[f.ID] = f
255
 		functions[f.ID] = f
247
 	}
256
 	}
248
 
257
 
249
-	locations := make(map[uint64]*Location)
258
+	locations := make(map[uint64]*Location, len(p.Location))
259
+	locationIds := make([]*Location, len(p.Location)+1)
250
 	for _, l := range p.Location {
260
 	for _, l := range p.Location {
251
-		l.Mapping = mappings[l.mappingIDX]
261
+		if id := l.mappingIDX; id < uint64(len(mappingIds)) {
262
+			l.Mapping = mappingIds[id]
263
+		} else {
264
+			l.Mapping = mappings[id]
265
+		}
252
 		l.mappingIDX = 0
266
 		l.mappingIDX = 0
253
 		for i, ln := range l.Line {
267
 		for i, ln := range l.Line {
254
 			if id := ln.functionIDX; id != 0 {
268
 			if id := ln.functionIDX; id != 0 {
255
-				l.Line[i].Function = functions[id]
256
-				if l.Line[i].Function == nil {
257
-					return fmt.Errorf("Function ID %d not found", id)
258
-				}
259
 				l.Line[i].functionIDX = 0
269
 				l.Line[i].functionIDX = 0
270
+				if id < uint64(len(functionIds)) {
271
+					l.Line[i].Function = functionIds[id]
272
+					continue
273
+				}
274
+				l.Line[i].Function = functions[id]
260
 			}
275
 			}
261
 		}
276
 		}
277
+		if l.ID < uint64(len(locationIds)) {
278
+			locationIds[l.ID] = l
279
+			continue
280
+		}
262
 		locations[l.ID] = l
281
 		locations[l.ID] = l
263
 	}
282
 	}
264
 
283
 
268
 	}
287
 	}
269
 
288
 
270
 	for _, s := range p.Sample {
289
 	for _, s := range p.Sample {
271
-		labels := make(map[string][]string)
272
-		numLabels := make(map[string][]int64)
290
+		labels := make(map[string][]string, len(s.labelX))
291
+		numLabels := make(map[string][]int64, len(s.labelX))
273
 		for _, l := range s.labelX {
292
 		for _, l := range s.labelX {
274
 			var key, value string
293
 			var key, value string
275
 			key, err = getString(p.stringTable, &l.keyX, err)
294
 			key, err = getString(p.stringTable, &l.keyX, err)
288
 		}
307
 		}
289
 		s.Location = make([]*Location, len(s.locationIDX))
308
 		s.Location = make([]*Location, len(s.locationIDX))
290
 		for i, lid := range s.locationIDX {
309
 		for i, lid := range s.locationIDX {
310
+			if lid < uint64(len(locationIds)) {
311
+				s.Location[i] = locationIds[lid]
312
+				continue
313
+			}
291
 			s.Location[i] = locations[lid]
314
 			s.Location[i] = locations[lid]
292
 		}
315
 		}
293
 		s.locationIDX = nil
316
 		s.locationIDX = nil