fastdelta

package
v1.60.2-rc.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 13, 2024 License: Apache-2.0, BSD-3-Clause, Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package fastdelta tries to match up samples between two pprof profiles and take their difference. A sample is a unique (call stack, labels) pair with an associated sequence of values, where "call stack" refers to a sequence of program counters/instruction addresses, and labels are key/value pairs associated with a stack (so we can have the same call stack appear in two different samples if the labels are different)

The github.com/google/pprof already implements this functionality as profile.Merge, but unfortunately it's causing an extreme amount of allocations and memory usage. This package provides an alternative implementation that has been highly optimized to be allocation free once steady-state is reached (no more new samples are added) and to also use a minimum amount of memory and allocations while growing.

Implementation

Computing the delta profile takes six passes over the input:

Pass 1 * Build a mapping of location IDs to instruction addresses * Build the string table, so we can resolve label keys and values * Find the sample types by name, so we know which sample values to compute differences for

Pass 2 * For each sample, aggregate the value for the sample. The Go runtime heap profile can sometimes contain multiple samples with the same call stack and labels, which should actually be aggregated into one sample.

Pass 3 * Compute the delta values for each sample usings its previous values and write them out if this leaves us with at least one non-zero values. * Update the previous sample values for the next round. * Keep track of the locations and strings we need given the samples we wrote out.

Pass 4 * Write out all fields that were referenced by the samples in Pass 3. * Keep track of strings and function ids we need to emit in the next pass.

Pass 5 * Write out the functions we need and keep track of their strings.

Pass 6 * Write out all the strings that were referenced by previous passes. * For strings not referenced, write out a zero-length byte to save space while preserving index references in the included messages

Note: It's possible to do all of the above with less passes, but doing so requires keeping more stuff in memory. Since extra passes are relatively cheap and our CPU usage is pretty low (~100ms for a 10MB heap profile), we prefer optimizing for lower memory usage as there is a larger chance that customers will complain about it.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DeltaComputer

type DeltaComputer struct {
	// contains filtered or unexported fields
}

DeltaComputer calculates the difference between pprof-encoded profiles

func NewDeltaComputer

func NewDeltaComputer(fields ...pprofutils.ValueType) *DeltaComputer

NewDeltaComputer initializes a DeltaComputer which will calculate the difference between the values for profile samples whose fields have the given names (e.g. "alloc_space", "contention", ...)

func (*DeltaComputer) Delta

func (dc *DeltaComputer) Delta(p []byte, out io.Writer) error

Delta calculates the difference between the pprof-encoded profile p and the profile passed in to the previous call to Delta. The encoded delta profile will be written to out.

The first time Delta is called, the internal state of the DeltaComputer will be updated and the profile will be written unchanged.

type DeltaMap

type DeltaMap struct {
	// contains filtered or unexported fields
}

DeltaMap ...

func NewDeltaMap

func NewDeltaMap(st *stringTable, lx *locationIndex, fields []valueType) *DeltaMap

NewDeltaMap ...

func (*DeltaMap) AddSampleType

func (dm *DeltaMap) AddSampleType(st *pproflite.SampleType) error

AddSampleType ...

func (*DeltaMap) Delta

func (dm *DeltaMap) Delta(sample *pproflite.Sample) (bool, error)

Delta updates sample.Value by looking up the previous values for this sample and substracting them from the current values. The returned boolean is true if the the new sample.Value contains at least one non-zero value.

func (*DeltaMap) Reset

func (dm *DeltaMap) Reset()

Reset ...

func (*DeltaMap) UpdateSample

func (dm *DeltaMap) UpdateSample(sample *pproflite.Sample) error

UpdateSample ...

type DenseIntSet

type DenseIntSet struct {
	// contains filtered or unexported fields
}

DenseIntSet ...

func (*DenseIntSet) Add

func (d *DenseIntSet) Add(vals ...int) bool

Add ...

func (*DenseIntSet) Append

func (d *DenseIntSet) Append(val bool)

Append ...

func (*DenseIntSet) Contains

func (d *DenseIntSet) Contains(val int) bool

Contains ...

func (*DenseIntSet) Reset

func (d *DenseIntSet) Reset()

Reset ...

type Hash

type Hash [16]byte

Hash is a 128-bit hash representing sample identity

type Hasher

type Hasher struct {
	// contains filtered or unexported fields
}

Hasher ...

func (*Hasher) Sample

func (h *Hasher) Sample(s *pproflite.Sample) (Hash, error)

Sample ...

type SparseIntSet

type SparseIntSet struct {
	// contains filtered or unexported fields
}

SparseIntSet ...

func (*SparseIntSet) Add

func (s *SparseIntSet) Add(i int)

Add ...

func (*SparseIntSet) Contains

func (s *SparseIntSet) Contains(i int) bool

Contains ...

func (*SparseIntSet) Reset

func (s *SparseIntSet) Reset()

Reset ...

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL