예제 #1
0
파일: driver.go 프로젝트: google/pprof
func aggregate(prof *profile.Profile, v variables) error {
	var inlines, function, filename, linenumber, address bool
	switch {
	case v["addresses"].boolValue():
		return nil
	case v["lines"].boolValue():
		inlines = true
		function = true
		filename = true
		linenumber = true
	case v["files"].boolValue():
		inlines = true
		filename = true
	case v["functions"].boolValue():
		inlines = true
		function = true
		filename = true
	case v["noinlines"].boolValue():
		function = true
		filename = true
	case v["addressnoinlines"].boolValue():
		function = true
		filename = true
		linenumber = true
		address = true
	case v["functionnameonly"].boolValue():
		inlines = true
		function = true
	default:
		return fmt.Errorf("unexpected granularity")
	}
	return prof.Aggregate(inlines, function, filename, linenumber, address)
}
예제 #2
0
// applyFocus filters samples based on the focus/ignore options
func applyFocus(prof *profile.Profile, v variables, ui plugin.UI) error {
	focus, err := compileRegexOption("focus", v["focus"].value, nil)
	ignore, err := compileRegexOption("ignore", v["ignore"].value, err)
	hide, err := compileRegexOption("hide", v["hide"].value, err)
	show, err := compileRegexOption("show", v["show"].value, err)
	tagfocus, err := compileTagFilter("tagfocus", v["tagfocus"].value, ui, err)
	tagignore, err := compileTagFilter("tagignore", v["tagignore"].value, ui, err)
	prunefrom, err := compileRegexOption("prune_from", v["prune_from"].value, err)
	if err != nil {
		return err
	}

	fm, im, hm, hnm := prof.FilterSamplesByName(focus, ignore, hide, show)
	warnNoMatches(focus == nil || fm, "Focus", ui)
	warnNoMatches(ignore == nil || im, "Ignore", ui)
	warnNoMatches(hide == nil || hm, "Hide", ui)
	warnNoMatches(show == nil || hnm, "Show", ui)

	tfm, tim := prof.FilterSamplesByTag(tagfocus, tagignore)
	warnNoMatches(tagfocus == nil || tfm, "TagFocus", ui)
	warnNoMatches(tagignore == nil || tim, "TagIgnore", ui)

	tagshow, err := compileRegexOption("tagshow", v["tagshow"].value, err)
	taghide, err := compileRegexOption("taghide", v["taghide"].value, err)
	tns, tnh := prof.FilterTagsByName(tagshow, taghide)
	warnNoMatches(tagshow == nil || tns, "TagShow", ui)
	warnNoMatches(tagignore == nil || tnh, "TagHide", ui)

	if prunefrom != nil {
		prof.PruneFrom(prunefrom)
	}
	return nil
}
예제 #3
0
func printTopProto(w io.Writer, rpt *Report) error {
	p := rpt.prof
	o := rpt.options
	g, _, _, _ := rpt.newTrimmedGraph()
	rpt.selectOutputUnit(g)

	out := profile.Profile{
		SampleType: []*profile.ValueType{
			{Type: "cum", Unit: o.OutputUnit},
			{Type: "flat", Unit: o.OutputUnit},
		},
		TimeNanos:     p.TimeNanos,
		DurationNanos: p.DurationNanos,
		PeriodType:    p.PeriodType,
		Period:        p.Period,
	}
	var flatSum int64
	for i, n := range g.Nodes {
		name, flat, cum := n.Info.PrintableName(), n.Flat, n.Cum

		flatSum += flat
		f := &profile.Function{
			ID:         uint64(i + 1),
			Name:       name,
			SystemName: name,
		}
		l := &profile.Location{
			ID: uint64(i + 1),
			Line: []profile.Line{
				{
					Function: f,
				},
			},
		}

		fv, _ := measurement.Scale(flat, o.SampleUnit, o.OutputUnit)
		cv, _ := measurement.Scale(cum, o.SampleUnit, o.OutputUnit)
		s := &profile.Sample{
			Location: []*profile.Location{l},
			Value:    []int64{int64(cv), int64(fv)},
		}
		out.Function = append(out.Function, f)
		out.Location = append(out.Location, l)
		out.Sample = append(out.Sample, s)
	}

	return out.Write(w)
}
예제 #4
0
파일: driver.go 프로젝트: google/pprof
func generateReport(p *profile.Profile, cmd []string, vars variables, o *plugin.Options) error {
	p = p.Copy() // Prevent modification to the incoming profile.

	var w io.Writer
	switch output := vars["output"].value; output {
	case "":
		w = os.Stdout
	default:
		o.UI.PrintErr("Generating report in ", output)
		outputFile, err := o.Writer.Open(output)
		if err != nil {
			return err
		}
		defer outputFile.Close()
		w = outputFile
	}

	vars = applyCommandOverrides(cmd, vars)

	// Delay focus after configuring report to get percentages on all samples.
	relative := vars["relative_percentages"].boolValue()
	if relative {
		if err := applyFocus(p, vars, o.UI); err != nil {
			return err
		}
	}
	ropt, err := reportOptions(p, vars)
	if err != nil {
		return err
	}
	c := pprofCommands[cmd[0]]
	if c == nil {
		panic("unexpected nil command")
	}
	ropt.OutputFormat = c.format
	post := c.postProcess
	if len(cmd) == 2 {
		s, err := regexp.Compile(cmd[1])
		if err != nil {
			return fmt.Errorf("parsing argument regexp %s: %v", cmd[1], err)
		}
		ropt.Symbol = s
	}

	rpt := report.New(p, ropt)
	if !relative {
		if err := applyFocus(p, vars, o.UI); err != nil {
			return err
		}
	}

	if err := aggregate(p, vars); err != nil {
		return err
	}

	if post == nil {
		return report.Generate(w, rpt, o.Obj)
	}

	// Capture output into buffer and send to postprocessing command.
	buf := &bytes.Buffer{}
	if err := report.Generate(buf, rpt, o.Obj); err != nil {
		return err
	}
	return post(buf.Bytes(), w, o.UI)
}
예제 #5
0
// symbolizeMapping symbolizes locations belonging to a Mapping by querying
// a symbolz handler. An offset is applied to all addresses to take care of
// normalization occured for merged Mappings.
func symbolizeMapping(source string, offset int64, syms func(string, string) ([]byte, error), m *profile.Mapping, p *profile.Profile) error {
	// Construct query of addresses to symbolize.
	var a []string
	for _, l := range p.Location {
		if l.Mapping == m && l.Address != 0 && len(l.Line) == 0 {
			// Compensate for normalization.
			addr := int64(l.Address) + offset
			if addr < 0 {
				return fmt.Errorf("unexpected negative adjusted address, mapping %v source %d, offset %d", l.Mapping, l.Address, offset)
			}
			a = append(a, fmt.Sprintf("%#x", addr))
		}
	}

	if len(a) == 0 {
		// No addresses to symbolize.
		return nil
	}

	lines := make(map[uint64]profile.Line)
	functions := make(map[string]*profile.Function)

	b, err := syms(source, strings.Join(a, "+"))
	if err != nil {
		return err
	}

	buf := bytes.NewBuffer(b)
	for {
		l, err := buf.ReadString('\n')

		if err != nil {
			if err == io.EOF {
				break
			}
			return err
		}

		if symbol := symbolzRE.FindStringSubmatch(l); len(symbol) == 3 {
			addr, err := strconv.ParseInt(symbol[1], 0, 64)
			if err != nil {
				return fmt.Errorf("unexpected parse failure %s: %v", symbol[1], err)
			}
			if addr < 0 {
				return fmt.Errorf("unexpected negative adjusted address, source %s, offset %d", symbol[1], offset)
			}
			// Reapply offset expected by the profile.
			addr -= offset

			name := symbol[2]
			fn := functions[name]
			if fn == nil {
				fn = &profile.Function{
					ID:         uint64(len(p.Function) + 1),
					Name:       name,
					SystemName: name,
				}
				functions[name] = fn
				p.Function = append(p.Function, fn)
			}

			lines[uint64(addr)] = profile.Line{Function: fn}
		}
	}

	for _, l := range p.Location {
		if l.Mapping != m {
			continue
		}
		if line, ok := lines[l.Address]; ok {
			l.Line = []profile.Line{line}
		}
	}

	return nil
}
예제 #6
0
func localMock(mode string, p *profile.Profile, obj plugin.ObjTool, ui plugin.UI) error {
	p.Comments = append(p.Comments, "local="+mode)
	return nil
}
예제 #7
0
func symbolzMock(sources plugin.MappingSources, syms func(string, string) ([]byte, error), p *profile.Profile, ui plugin.UI) error {
	p.Comments = append(p.Comments, "symbolz")
	return nil
}