浏览代码

Merge pull request #17 from rauls5382/master

Add source_path option to point pprof to source files
Josef Jelinek 9 年前
父节点
当前提交
9e62056af5
共有 5 个文件被更改,包括 46 次插入18 次删除
  1. 1
    0
      internal/driver/commands.go
  2. 2
    0
      internal/driver/driver.go
  3. 2
    0
      internal/driver/interactive.go
  4. 2
    1
      internal/report/report.go
  5. 39
    17
      internal/report/source.go

+ 1
- 0
internal/driver/commands.go 查看文件

@@ -152,6 +152,7 @@ var pprofVariables = variables{
152 152
 		" For memory profiles, use megabytes, kilobytes, bytes, etc.",
153 153
 		" auto will scale each value independently to the most natural unit.")},
154 154
 	"compact_labels": &variable{boolKind, "f", "", "Show minimal headers"},
155
+	"source_path":    &variable{stringKind, "", "", "Search path for source files"},
155 156
 
156 157
 	// Filtering options
157 158
 	"nodecount": &variable{intKind, "-1", "", helpText(

+ 2
- 0
internal/driver/driver.go 查看文件

@@ -235,6 +235,8 @@ func reportOptions(p *profile.Profile, vars variables) (*report.Options, error)
235 235
 		SampleUnit:  sample.Unit,
236 236
 
237 237
 		OutputUnit: vars["unit"].value,
238
+
239
+		SourcePath: vars["source_path"].stringValue(),
238 240
 	}
239 241
 
240 242
 	if len(p.Mapping) > 0 && p.Mapping[0].File != "" {

+ 2
- 0
internal/driver/interactive.go 查看文件

@@ -167,6 +167,8 @@ func pprofPrompt(p *profile.Profile) string {
167 167
 			if o.boolValue() == false {
168 168
 				continue
169 169
 			}
170
+		case n == "source_path":
171
+			continue
170 172
 		}
171 173
 		args = append(args, fmt.Sprintf("  %-25s : %s", n, v))
172 174
 	}

+ 2
- 1
internal/report/report.go 查看文件

@@ -881,7 +881,8 @@ type Options struct {
881 881
 
882 882
 	OutputUnit string // Units for data formatting in report.
883 883
 
884
-	Symbol *regexp.Regexp // Symbols to include on disassembly report.
884
+	Symbol     *regexp.Regexp // Symbols to include on disassembly report.
885
+	SourcePath string         // Search path for source files.
885 886
 }
886 887
 
887 888
 // New builds a new report indexing the sample values interpreting the

+ 39
- 17
internal/report/source.go 查看文件

@@ -55,6 +55,15 @@ func printSource(w io.Writer, rpt *Report) error {
55 55
 	}
56 56
 	functions.Sort(graph.NameOrder)
57 57
 
58
+	sourcePath := o.SourcePath
59
+	if sourcePath == "" {
60
+		wd, err := os.Getwd()
61
+		if err != nil {
62
+			return fmt.Errorf("Could not stat current dir: %v", err)
63
+		}
64
+		sourcePath = wd
65
+	}
66
+
58 67
 	fmt.Fprintf(w, "Total: %s\n", rpt.formatValue(rpt.total))
59 68
 	for _, fn := range functions {
60 69
 		name := fn.Info.Name
@@ -86,7 +95,7 @@ func printSource(w io.Writer, rpt *Report) error {
86 95
 			fns := fileNodes[filename]
87 96
 			flatSum, cumSum := fns.Sum()
88 97
 
89
-			fnodes, path, err := getFunctionSource(name, filename, fns, 0, 0)
98
+			fnodes, path, err := getFunctionSource(name, filename, sourcePath, fns, 0, 0)
90 99
 			fmt.Fprintf(w, "ROUTINE ======================== %s in %s\n", name, path)
91 100
 			fmt.Fprintf(w, "%10s %10s (flat, cum) %s of Total\n",
92 101
 				rpt.formatValue(flatSum), rpt.formatValue(cumSum),
@@ -118,6 +127,15 @@ func printWebSource(w io.Writer, rpt *Report, obj plugin.ObjTool) error {
118 127
 		address = &hex
119 128
 	}
120 129
 
130
+	sourcePath := o.SourcePath
131
+	if sourcePath == "" {
132
+		wd, err := os.Getwd()
133
+		if err != nil {
134
+			return fmt.Errorf("Could not stat current dir: %v", err)
135
+		}
136
+		sourcePath = wd
137
+	}
138
+
121 139
 	// Extract interesting symbols from binary files in the profile and
122 140
 	// classify samples per symbol.
123 141
 	symbols := symbolsFromBinaries(rpt.prof, g, o.Symbol, address, obj)
@@ -166,7 +184,7 @@ func printWebSource(w io.Writer, rpt *Report, obj plugin.ObjTool) error {
166 184
 			asm := assemblyPerSourceLine(symbols, fns, filename, obj)
167 185
 			start, end := sourceCoordinates(asm)
168 186
 
169
-			fnodes, path, err := getFunctionSource(name, filename, fns, start, end)
187
+			fnodes, path, err := getFunctionSource(name, filename, sourcePath, fns, start, end)
170 188
 			if err != nil {
171 189
 				fnodes, path = getMissingFunctionSource(filename, asm, start, end)
172 190
 			}
@@ -319,8 +337,8 @@ func printPageClosing(w io.Writer) {
319 337
 // getFunctionSource collects the sources of a function from a source
320 338
 // file and annotates it with the samples in fns. Returns the sources
321 339
 // as nodes, using the info.name field to hold the source code.
322
-func getFunctionSource(fun, file string, fns graph.Nodes, start, end int) (graph.Nodes, string, error) {
323
-	f, file, err := adjustSourcePath(file)
340
+func getFunctionSource(fun, file, sourcePath string, fns graph.Nodes, start, end int) (graph.Nodes, string, error) {
341
+	f, file, err := openSourceFile(file, sourcePath)
324 342
 	if err != nil {
325 343
 		return nil, file, err
326 344
 	}
@@ -411,31 +429,35 @@ func getMissingFunctionSource(filename string, asm map[int]graph.Nodes, start, e
411 429
 	return fnodes, filename
412 430
 }
413 431
 
414
-// adjustSourcePath adjusts the path for a source file by trimmming
415
-// known prefixes and searching for the file on all parents of the
416
-// current working dir.
417
-func adjustSourcePath(path string) (*os.File, string, error) {
432
+// openSourceFile opens a source file from a name encoded in a
433
+// profile. File names in a profile after often relative paths, so
434
+// search them in each of the paths in searchPath (or CWD by default),
435
+// and their parents.
436
+func openSourceFile(path, searchPath string) (*os.File, string, error) {
418 437
 	path = trimPath(path)
419
-	f, err := os.Open(path)
420
-	if err == nil {
421
-		return f, path, nil
438
+
439
+	if filepath.IsAbs(path) {
440
+		f, err := os.Open(path)
441
+		return f, path, err
422 442
 	}
423 443
 
424
-	if dir, wderr := os.Getwd(); wderr == nil {
444
+	// Scan each component of the path
445
+	for _, dir := range strings.Split(searchPath, ":") {
446
+		// Search up for every parent of each possible path.
425 447
 		for {
448
+			filename := filepath.Join(dir, path)
449
+			if f, err := os.Open(filename); err == nil {
450
+				return f, filename, nil
451
+			}
426 452
 			parent := filepath.Dir(dir)
427 453
 			if parent == dir {
428 454
 				break
429 455
 			}
430
-			if f, err := os.Open(filepath.Join(parent, path)); err == nil {
431
-				return f, filepath.Join(parent, path), nil
432
-			}
433
-
434 456
 			dir = parent
435 457
 		}
436 458
 	}
437 459
 
438
-	return nil, path, err
460
+	return nil, "", fmt.Errorf("Could not find file %s on path %s", path, searchPath)
439 461
 }
440 462
 
441 463
 // trimPath cleans up a path by removing prefixes that are commonly