Browse Source

Merge pull request #20 from rauls5382/master

Allow weblist to work even if assembly is not available
Josef Jelinek 9 years ago
parent
commit
e46b1ad71b
2 changed files with 53 additions and 49 deletions
  1. 3
    0
      internal/graph/graph.go
  2. 50
    49
      internal/report/source.go

+ 3
- 0
internal/graph/graph.go View File

@@ -776,6 +776,9 @@ func (ns Nodes) Sort(o NodeOrder) error {
776 776
 				if iv, jv := l.Info.File, r.Info.File; iv != jv {
777 777
 					return iv < jv
778 778
 				}
779
+				if iv, jv := l.Info.StartLine, r.Info.StartLine; iv != jv {
780
+					return iv < jv
781
+				}
779 782
 				return compareNodes(l, r)
780 783
 			},
781 784
 		}

+ 50
- 49
internal/report/source.go View File

@@ -24,7 +24,6 @@ import (
24 24
 	"io"
25 25
 	"os"
26 26
 	"path/filepath"
27
-	"sort"
28 27
 	"strconv"
29 28
 	"strings"
30 29
 
@@ -95,8 +94,8 @@ func printSource(w io.Writer, rpt *Report) error {
95 94
 			fns := fileNodes[filename]
96 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 99
 			fmt.Fprintf(w, "%10s %10s (flat, cum) %s of Total\n",
101 100
 				rpt.formatValue(flatSum), rpt.formatValue(cumSum),
102 101
 				percentage(cumSum, rpt.total))
@@ -136,66 +135,68 @@ func printWebSource(w io.Writer, rpt *Report, obj plugin.ObjTool) error {
136 135
 		sourcePath = wd
137 136
 	}
138 137
 
138
+	type fileFunction struct {
139
+		fileName, functionName string
140
+	}
141
+
139 142
 	// Extract interesting symbols from binary files in the profile and
140 143
 	// classify samples per symbol.
141 144
 	symbols := symbolsFromBinaries(rpt.prof, g, o.Symbol, address, obj)
142 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 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 201
 	printPageClosing(w)
201 202
 	return nil
@@ -334,10 +335,10 @@ func printPageClosing(w io.Writer) {
334 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 339
 // file and annotates it with the samples in fns. Returns the sources
339 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 342
 	file = trimPath(file)
342 343
 	f, err := openSourceFile(file, sourcePath)
343 344
 	if err != nil {