浏览代码

Merge pull request #20 from rauls5382/master

Allow weblist to work even if assembly is not available
Josef Jelinek 9 年前
父节点
当前提交
e46b1ad71b
共有 2 个文件被更改,包括 53 次插入49 次删除
  1. 3
    0
      internal/graph/graph.go
  2. 50
    49
      internal/report/source.go

+ 3
- 0
internal/graph/graph.go 查看文件

776
 				if iv, jv := l.Info.File, r.Info.File; iv != jv {
776
 				if iv, jv := l.Info.File, r.Info.File; iv != jv {
777
 					return iv < jv
777
 					return iv < jv
778
 				}
778
 				}
779
+				if iv, jv := l.Info.StartLine, r.Info.StartLine; iv != jv {
780
+					return iv < jv
781
+				}
779
 				return compareNodes(l, r)
782
 				return compareNodes(l, r)
780
 			},
783
 			},
781
 		}
784
 		}

+ 50
- 49
internal/report/source.go 查看文件

24
 	"io"
24
 	"io"
25
 	"os"
25
 	"os"
26
 	"path/filepath"
26
 	"path/filepath"
27
-	"sort"
28
 	"strconv"
27
 	"strconv"
29
 	"strings"
28
 	"strings"
30
 
29
 
95
 			fns := fileNodes[filename]
94
 			fns := fileNodes[filename]
96
 			flatSum, cumSum := fns.Sum()
95
 			flatSum, cumSum := fns.Sum()
97
 
96
 
98
-			fnodes, path, err := getFunctionSource(name, filename, sourcePath, fns, 0, 0)
99
-			fmt.Fprintf(w, "ROUTINE ======================== %s in %s\n", name, path)
97
+			fnodes, _, err := getSourceFromFile(filename, sourcePath, fns, 0, 0)
98
+			fmt.Fprintf(w, "ROUTINE ======================== %s in %s\n", name, filename)
100
 			fmt.Fprintf(w, "%10s %10s (flat, cum) %s of Total\n",
99
 			fmt.Fprintf(w, "%10s %10s (flat, cum) %s of Total\n",
101
 				rpt.formatValue(flatSum), rpt.formatValue(cumSum),
100
 				rpt.formatValue(flatSum), rpt.formatValue(cumSum),
102
 				percentage(cumSum, rpt.total))
101
 				percentage(cumSum, rpt.total))
136
 		sourcePath = wd
135
 		sourcePath = wd
137
 	}
136
 	}
138
 
137
 
138
+	type fileFunction struct {
139
+		fileName, functionName string
140
+	}
141
+
139
 	// Extract interesting symbols from binary files in the profile and
142
 	// Extract interesting symbols from binary files in the profile and
140
 	// classify samples per symbol.
143
 	// classify samples per symbol.
141
 	symbols := symbolsFromBinaries(rpt.prof, g, o.Symbol, address, obj)
144
 	symbols := symbolsFromBinaries(rpt.prof, g, o.Symbol, address, obj)
142
 	symNodes := nodesPerSymbol(g.Nodes, symbols)
145
 	symNodes := nodesPerSymbol(g.Nodes, symbols)
143
 
146
 
144
-	// Sort symbols for printing.
145
-	var syms objSymbols
146
-	for s := range symNodes {
147
-		syms = append(syms, s)
148
-	}
149
-	sort.Sort(syms)
150
-
151
-	if len(syms) == 0 {
152
-		return fmt.Errorf("no samples found on routines matching: %s", o.Symbol.String())
153
-	}
154
-
155
-	printHeader(w, rpt)
156
-	for _, s := range syms {
157
-		name := s.sym.Name[0]
158
-		// Identify sources associated to a symbol by examining
159
-		// symbol samples. Classify samples per source file.
160
-		var sourceFiles graph.Nodes
161
-		fileNodes := make(map[string]graph.Nodes)
162
-		for _, n := range symNodes[s] {
163
-			if n.Info.File == "" {
147
+	// Identify sources associated to a symbol by examining
148
+	// symbol samples. Classify samples per source file.
149
+	fileNodes := make(map[fileFunction]graph.Nodes)
150
+	if len(symNodes) == 0 {
151
+		for _, n := range g.Nodes {
152
+			if n.Info.File == "" || !o.Symbol.MatchString(n.Info.Name) {
164
 				continue
153
 				continue
165
 			}
154
 			}
166
-			if fileNodes[n.Info.File] == nil {
167
-				sourceFiles = append(sourceFiles, n)
155
+			ff := fileFunction{n.Info.File, n.Info.Name}
156
+			fileNodes[ff] = append(fileNodes[ff], n)
157
+		}
158
+	} else {
159
+		for _, nodes := range symNodes {
160
+			for _, n := range nodes {
161
+				if n.Info.File != "" {
162
+					ff := fileFunction{n.Info.File, n.Info.Name}
163
+					fileNodes[ff] = append(fileNodes[ff], n)
164
+				}
168
 			}
165
 			}
169
-			fileNodes[n.Info.File] = append(fileNodes[n.Info.File], n)
170
 		}
166
 		}
167
+	}
171
 
168
 
172
-		if len(sourceFiles) == 0 {
173
-			fmt.Fprintf(w, "No source information for %s\n", name)
174
-			continue
175
-		}
169
+	if len(fileNodes) == 0 {
170
+		return fmt.Errorf("No source information for %s\n", o.Symbol.String())
171
+	}
176
 
172
 
177
-		sourceFiles.Sort(graph.FileOrder)
173
+	sourceFiles := make(graph.Nodes, 0, len(fileNodes))
174
+	for _, nodes := range fileNodes {
175
+		sNode := *nodes[0]
176
+		sNode.Flat, sNode.Cum = nodes.Sum()
177
+		sourceFiles = append(sourceFiles, &sNode)
178
+	}
179
+	sourceFiles.Sort(graph.FileOrder)
178
 
180
 
179
-		// Print each file associated with this function.
180
-		for _, fl := range sourceFiles {
181
-			filename := fl.Info.File
182
-			fns := fileNodes[filename]
181
+	// Print each file associated with this function.
182
+	printHeader(w, rpt)
183
+	for _, n := range sourceFiles {
184
+		ff := fileFunction{n.Info.File, n.Info.Name}
185
+		fns := fileNodes[ff]
183
 
186
 
184
-			asm := assemblyPerSourceLine(symbols, fns, filename, obj)
185
-			start, end := sourceCoordinates(asm)
187
+		asm := assemblyPerSourceLine(symbols, fns, ff.fileName, obj)
188
+		start, end := sourceCoordinates(asm)
186
 
189
 
187
-			fnodes, path, err := getFunctionSource(name, filename, sourcePath, fns, start, end)
188
-			if err != nil {
189
-				fnodes, path = getMissingFunctionSource(filename, asm, start, end)
190
-			}
190
+		fnodes, path, err := getSourceFromFile(ff.fileName, sourcePath, fns, start, end)
191
+		if err != nil {
192
+			fnodes, path = getMissingFunctionSource(ff.fileName, asm, start, end)
193
+		}
191
 
194
 
192
-			flatSum, cumSum := fnodes.Sum()
193
-			printFunctionHeader(w, name, path, flatSum, cumSum, rpt)
194
-			for _, fn := range fnodes {
195
-				printFunctionSourceLine(w, fn, asm[fn.Info.Lineno], rpt)
196
-			}
197
-			printFunctionClosing(w)
195
+		printFunctionHeader(w, ff.functionName, path, n.Flat, n.Cum, rpt)
196
+		for _, fn := range fnodes {
197
+			printFunctionSourceLine(w, fn, asm[fn.Info.Lineno], rpt)
198
 		}
198
 		}
199
+		printFunctionClosing(w)
199
 	}
200
 	}
200
 	printPageClosing(w)
201
 	printPageClosing(w)
201
 	return nil
202
 	return nil
334
 	fmt.Fprintln(w, weblistPageClosing)
335
 	fmt.Fprintln(w, weblistPageClosing)
335
 }
336
 }
336
 
337
 
337
-// getFunctionSource collects the sources of a function from a source
338
+// getSourceFromFile collects the sources of a function from a source
338
 // file and annotates it with the samples in fns. Returns the sources
339
 // file and annotates it with the samples in fns. Returns the sources
339
 // as nodes, using the info.name field to hold the source code.
340
 // as nodes, using the info.name field to hold the source code.
340
-func getFunctionSource(fun, file, sourcePath string, fns graph.Nodes, start, end int) (graph.Nodes, string, error) {
341
+func getSourceFromFile(file, sourcePath string, fns graph.Nodes, start, end int) (graph.Nodes, string, error) {
341
 	file = trimPath(file)
342
 	file = trimPath(file)
342
 	f, err := openSourceFile(file, sourcePath)
343
 	f, err := openSourceFile(file, sourcePath)
343
 	if err != nil {
344
 	if err != nil {