浏览代码

Speed up graph.New

Non functional changes -- pre-size maps and slices to reduce
cost of building a graph out of a profile.
Raul Silvera 9 年前
父节点
当前提交
9f07e766be
共有 1 个文件被更改,包括 28 次插入18 次删除
  1. 28
    18
      internal/graph/graph.go

+ 28
- 18
internal/graph/graph.go 查看文件

20
 	"math"
20
 	"math"
21
 	"path/filepath"
21
 	"path/filepath"
22
 	"sort"
22
 	"sort"
23
+	"strconv"
23
 	"strings"
24
 	"strings"
24
 
25
 
25
 	"github.com/google/pprof/profile"
26
 	"github.com/google/pprof/profile"
156
 // If parent is non-nil, return a match with the same parent.
157
 // If parent is non-nil, return a match with the same parent.
157
 // If kept is non-nil, nodes are only added if they can be located on it.
158
 // If kept is non-nil, nodes are only added if they can be located on it.
158
 func (m NodeMap) FindOrInsertNode(info NodeInfo, parent *Node, kept NodeSet) *Node {
159
 func (m NodeMap) FindOrInsertNode(info NodeInfo, parent *Node, kept NodeSet) *Node {
159
-	if kept != nil && !kept[info] {
160
-		return nil
160
+	if kept != nil {
161
+		if _, ok := kept[info]; !ok {
162
+			return nil
163
+		}
161
 	}
164
 	}
162
 
165
 
163
 	extendedInfo := ExtendedNodeInfo{
166
 	extendedInfo := ExtendedNodeInfo{
165
 		parent,
168
 		parent,
166
 	}
169
 	}
167
 
170
 
168
-	if n := m[extendedInfo]; n != nil {
171
+	if n, ok := m[extendedInfo]; ok {
169
 		return n
172
 		return n
170
 	}
173
 	}
171
 
174
 
216
 
219
 
217
 // New summarizes performance data from a profile into a graph.
220
 // New summarizes performance data from a profile into a graph.
218
 func New(prof *profile.Profile, o *Options) (g *Graph) {
221
 func New(prof *profile.Profile, o *Options) (g *Graph) {
222
+	const averageNodesPerLocation = 2
219
 	locations := NewLocInfo(prof, o.ObjNames)
223
 	locations := NewLocInfo(prof, o.ObjNames)
220
-	nm := make(NodeMap)
224
+	nm := make(NodeMap, len(prof.Location)*averageNodesPerLocation)
221
 	for _, sample := range prof.Sample {
225
 	for _, sample := range prof.Sample {
222
 		if sample.Location == nil {
226
 		if sample.Location == nil {
223
 			continue
227
 			continue
227
 		// Keep track of the index on the Sample for each frame,
231
 		// Keep track of the index on the Sample for each frame,
228
 		// to determine inlining status.
232
 		// to determine inlining status.
229
 
233
 
230
-		var stack []NodeInfo
231
-		var locIndex []int
234
+		stack := make([]NodeInfo, 0, len(sample.Location))
235
+		locIndex := make([]int, 0, len(sample.Location)*averageNodesPerLocation)
232
 		for i, loc := range sample.Location {
236
 		for i, loc := range sample.Location {
233
 			id := loc.ID
237
 			id := loc.ID
234
 			stack = append(stack, locations[id]...)
238
 			stack = append(stack, locations[id]...)
238
 		}
242
 		}
239
 
243
 
240
 		weight := o.SampleValue(sample.Value)
244
 		weight := o.SampleValue(sample.Value)
241
-		seenEdge := make(map[*Node]map[*Node]bool)
245
+		seenNode := make(map[*Node]bool, len(stack))
246
+		seenEdge := make(map[nodePair]bool, len(stack))
242
 		var nn *Node
247
 		var nn *Node
243
 		nlocIndex := -1
248
 		nlocIndex := -1
244
 		residual := false
249
 		residual := false
259
 				n.addSample(sample, weight, o.FormatTag, true)
264
 				n.addSample(sample, weight, o.FormatTag, true)
260
 			}
265
 			}
261
 			// Add cum weight to all nodes in stack, avoiding double counting.
266
 			// Add cum weight to all nodes in stack, avoiding double counting.
262
-			if seenEdge[n] == nil {
263
-				seenEdge[n] = make(map[*Node]bool)
267
+			if _, ok := seenNode[n]; !ok {
268
+				seenNode[n] = true
264
 				n.addSample(sample, weight, o.FormatTag, false)
269
 				n.addSample(sample, weight, o.FormatTag, false)
265
 			}
270
 			}
266
 			// Update edge weights for all edges in stack, avoiding double counting.
271
 			// Update edge weights for all edges in stack, avoiding double counting.
267
-			if nn != nil && n != nn && !seenEdge[n][nn] {
268
-				seenEdge[n][nn] = true
272
+			if _, ok := seenEdge[nodePair{n, nn}]; !ok && nn != nil && n != nn {
273
+				seenEdge[nodePair{n, nn}] = true
269
 				// This is an inlined edge if the caller and the callee
274
 				// This is an inlined edge if the caller and the callee
270
 				// correspond to the same entry in the sample.
275
 				// correspond to the same entry in the sample.
271
 				nn.BumpWeight(n, weight, residual, locIndex[i-1] == nlocIndex)
276
 				nn.BumpWeight(n, weight, residual, locIndex[i-1] == nlocIndex)
288
 	return &Graph{ns}
293
 	return &Graph{ns}
289
 }
294
 }
290
 
295
 
296
+type nodePair struct {
297
+	src, dest *Node
298
+}
299
+
291
 // isNegative returns true if the node is considered as "negative" for the
300
 // isNegative returns true if the node is considered as "negative" for the
292
 // purposes of drop_negative.
301
 // purposes of drop_negative.
293
 func isNegative(n *Node) bool {
302
 func isNegative(n *Node) bool {
409
 		n.NumericTags[joinedLabels] = numericTags
418
 		n.NumericTags[joinedLabels] = numericTags
410
 	}
419
 	}
411
 	// Add numeric tags
420
 	// Add numeric tags
421
+	if format == nil {
422
+		format = defaultLabelFormat
423
+	}
412
 	for key, nvals := range s.NumLabel {
424
 	for key, nvals := range s.NumLabel {
413
 		for _, v := range nvals {
425
 		for _, v := range nvals {
414
-			var label string
415
-			if format != nil {
416
-				label = format(v, key)
417
-			} else {
418
-				label = fmt.Sprintf("%d", v)
419
-			}
420
-			t := numericTags.findOrAddTag(label, key, v)
426
+			t := numericTags.findOrAddTag(format(v, key), key, v)
421
 			if flat {
427
 			if flat {
422
 				t.Flat += value
428
 				t.Flat += value
423
 			} else {
429
 			} else {
427
 	}
433
 	}
428
 }
434
 }
429
 
435
 
436
+func defaultLabelFormat(v int64, key string) string {
437
+	return strconv.FormatInt(v, 10)
438
+}
439
+
430
 func (m TagMap) findOrAddTag(label, unit string, value int64) *Tag {
440
 func (m TagMap) findOrAddTag(label, unit string, value int64) *Tag {
431
 	l := m[label]
441
 	l := m[label]
432
 	if l == nil {
442
 	if l == nil {