Explorar el Código

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 hace 8 años
padre
commit
74a2f64500
Se han modificado 1 ficheros con 34 adiciones y 11 borrados
  1. 34
    11
      profile/encode.go

+ 34
- 11
profile/encode.go Ver fichero

@@ -16,7 +16,6 @@ package profile
16 16
 
17 17
 import (
18 18
 	"errors"
19
-	"fmt"
20 19
 	"sort"
21 20
 )
22 21
 
@@ -231,34 +230,54 @@ var profileDecoder = []decoder{
231 230
 // The unexported fields are cleared up to facilitate testing.
232 231
 func (p *Profile) postDecode() error {
233 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 235
 	for _, m := range p.Mapping {
236 236
 		m.File, err = getString(p.stringTable, &m.fileX, err)
237 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 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 247
 	for _, f := range p.Function {
243 248
 		f.Name, err = getString(p.stringTable, &f.nameX, err)
244 249
 		f.SystemName, err = getString(p.stringTable, &f.systemNameX, err)
245 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 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 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 266
 		l.mappingIDX = 0
253 267
 		for i, ln := range l.Line {
254 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 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 281
 		locations[l.ID] = l
263 282
 	}
264 283
 
@@ -268,8 +287,8 @@ func (p *Profile) postDecode() error {
268 287
 	}
269 288
 
270 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 292
 		for _, l := range s.labelX {
274 293
 			var key, value string
275 294
 			key, err = getString(p.stringTable, &l.keyX, err)
@@ -288,6 +307,10 @@ func (p *Profile) postDecode() error {
288 307
 		}
289 308
 		s.Location = make([]*Location, len(s.locationIDX))
290 309
 		for i, lid := range s.locationIDX {
310
+			if lid < uint64(len(locationIds)) {
311
+				s.Location[i] = locationIds[lid]
312
+				continue
313
+			}
291 314
 			s.Location[i] = locations[lid]
292 315
 		}
293 316
 		s.locationIDX = nil