Пример #1
0
// printCountProfile prints a countProfile at the specified debug level.
func printCountProfile(w io.Writer, debug int, name string, p countProfile) error {
	prof := &profile.Profile{
		PeriodType: &profile.ValueType{Type: name, Unit: "count"},
		Period:     1,
		SampleType: []*profile.ValueType{{Type: name, Unit: "count"}},
	}
	locations := make(map[uint64]*profile.Location)

	count := map[string]int{}
	index := map[string]int{}
	var keys []string
	n := p.Len()
	for i := 0; i < n; i++ {
		k := makeKey(p.Stack(i))
		if count[k] == 0 {
			index[k] = i
			keys = append(keys, k)
		}
		count[k]++
	}

	sort.Sort(&keysByCount{keys, count})

	// Print stacks, listing count on first occurrence of a unique stack.
	for _, k := range keys {
		stk := p.Stack(index[k])
		if c := count[k]; c != 0 {
			locs := make([]*profile.Location, 0, len(stk))
			for _, addr := range stk {
				addr := uint64(addr)
				// Adjust all frames by -1 to land on the call instruction.
				addr--
				loc := locations[addr]
				if loc == nil {
					loc = &profile.Location{
						Address: addr,
					}
					locations[addr] = loc
					prof.Location = append(prof.Location, loc)
				}
				locs = append(locs, loc)
			}
			prof.Sample = append(prof.Sample, &profile.Sample{
				Location: locs,
				Value:    []int64{int64(c)},
			})
			delete(count, k)
		}
	}

	prof.RemapAll()
	protopprof.Symbolize(prof)
	return prof.Write(w)
}
Пример #2
0
func profileWriter(w io.Writer) {
	var buf bytes.Buffer
	for {
		data := runtime.CPUProfile()
		buf.Write(data)
		if data == nil {
			break
		}
	}
	p, err := protopprof.TranslateCPUProfile(buf.Bytes(), cpu.startTime)
	if err != nil {
		panic(err)
	}
	p.RemapAll()
	protopprof.CleanupDuplicateLocations(p)
	protopprof.Symbolize(p)
	p.Write(w)
	cpu.done <- true
}
Пример #3
0
// writeBlock writes the current blocking profile to w.
func writeBlock(w io.Writer, debug int) error {
	var p []runtime.BlockProfileRecord
	n, ok := runtime.BlockProfile(nil)
	for {
		// Code by analogy with writeBlock func
		p = make([]runtime.BlockProfileRecord, n+50)
		n, ok = runtime.BlockProfile(p)
		if ok {
			p = p[:n]
			break
		}
	}

	sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles })

	prof := &profile.Profile{
		PeriodType: &profile.ValueType{Type: "contentions", Unit: "count"},
		Period:     1,
		SampleType: []*profile.ValueType{
			{Type: "contentions", Unit: "count"},
			{Type: "delay", Unit: "nanoseconds"},
		},
	}

	cpuHz := runtime_cyclesPerSecond()
	locs := make(map[uint64]*profile.Location)
	for i := range p {
		r := &p[i]
		var v1, v2 int64
		v1 = r.Cycles
		v2 = r.Count
		if prof.Period > 0 {
			if cpuHz > 0 {
				cpuGHz := float64(cpuHz) / 1e9
				v1 = int64(float64(v1) * float64(prof.Period) / cpuGHz)
			}
			v2 = v2 * prof.Period
		}

		value := []int64{v2, v1}
		var sloc []*profile.Location

		for _, pc := range r.Stack() {
			addr := uint64(pc)
			addr--
			loc := locs[addr]
			if locs[addr] == nil {
				loc = &profile.Location{
					Address: addr,
				}
				prof.Location = append(prof.Location, loc)
				locs[addr] = loc
			}
			sloc = append(sloc, loc)
		}
		prof.Sample = append(prof.Sample, &profile.Sample{
			Value:    value,
			Location: sloc,
		})
	}

	prof.RemapAll()
	protopprof.Symbolize(prof)
	return prof.Write(w)
}
Пример #4
0
// writeHeap writes the current runtime heap profile to w.
func writeHeap(w io.Writer, debug int) error {
	// Find out how many records there are (MemProfile(nil, true)),
	// allocate that many records, and get the data.
	// There's a race—more records might be added between
	// the two calls—so allocate a few extra records for safety
	// and also try again if we're very unlucky.
	// The loop should only execute one iteration in the common case.
	var p []runtime.MemProfileRecord
	n, ok := runtime.MemProfile(nil, true)
	for {
		p = make([]runtime.MemProfileRecord, n+50)
		n, ok = runtime.MemProfile(p, true)
		if ok {
			p = p[0:n]
			break
		}
	}

	sort.Slice(p, func(i, j int) bool { return p[i].InUseBytes() > p[j].InUseBytes() })

	var total runtime.MemProfileRecord
	for i := range p {
		r := &p[i]
		total.AllocBytes += r.AllocBytes
		total.AllocObjects += r.AllocObjects
		total.FreeBytes += r.FreeBytes
		total.FreeObjects += r.FreeObjects
	}

	prof := &profile.Profile{
		PeriodType: &profile.ValueType{Type: "space", Unit: "bytes"},
		SampleType: []*profile.ValueType{
			{Type: "alloc_objects", Unit: "count"},
			{Type: "alloc_space", Unit: "bytes"},
			{Type: "inuse_objects", Unit: "count"},
			{Type: "inuse_space", Unit: "bytes"},
		},
		Period: int64(runtime.MemProfileRate),
	}

	locs := make(map[uint64]*(profile.Location))
	for i := range p {
		var v1, v2, v3, v4, blocksize int64
		r := &p[i]
		v1, v2 = int64(r.InUseObjects()), int64(r.InUseBytes())
		v3, v4 = int64(r.AllocObjects), int64(r.AllocBytes)
		if (v1 == 0 && v2 != 0) || (v3 == 0 && v4 != 0) {
			return fmt.Errorf("error writing memory profile: inuse object count was 0 but inuse bytes was %d", v2)
		} else {
			if v1 != 0 {
				blocksize = v2 / v1
				v1, v2 = scaleHeapSample(v1, v2, prof.Period)
			}
			if v3 != 0 {
				v3, v4 = scaleHeapSample(v3, v4, prof.Period)
			}
		}
		value := []int64{v1, v2, v3, v4}
		var sloc []*profile.Location
		for _, pc := range r.Stack() {
			addr := uint64(pc)
			addr--
			loc := locs[addr]
			if locs[addr] == nil {
				loc = &(profile.Location{
					Address: addr,
				})
				prof.Location = append(prof.Location, loc)
				locs[addr] = loc
			}
			sloc = append(sloc, loc)
		}
		prof.Sample = append(prof.Sample, &profile.Sample{
			Value:    value,
			Location: sloc,
			NumLabel: map[string][]int64{"bytes": {blocksize}},
		})
	}
	prof.RemapAll()
	protopprof.Symbolize(prof)
	return prof.Write(w)
}