| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| |
|
| | package profile |
| |
|
| | import ( |
| | "fmt" |
| | "regexp" |
| | "slices" |
| | "strings" |
| | ) |
| |
|
| | var ( |
| | reservedNames = []string{"(anonymous namespace)", "operator()"} |
| | bracketRx = func() *regexp.Regexp { |
| | var quotedNames []string |
| | for _, name := range append(reservedNames, "(") { |
| | quotedNames = append(quotedNames, regexp.QuoteMeta(name)) |
| | } |
| | return regexp.MustCompile(strings.Join(quotedNames, "|")) |
| | }() |
| | ) |
| |
|
| | |
| | func simplifyFunc(f string) string { |
| | |
| | funcName := strings.TrimPrefix(f, ".") |
| | |
| | |
| | for _, ind := range bracketRx.FindAllStringSubmatchIndex(funcName, -1) { |
| | foundReserved := slices.Contains(reservedNames, funcName[ind[0]:ind[1]]) |
| | if !foundReserved { |
| | funcName = funcName[:ind[0]] |
| | break |
| | } |
| | } |
| | return funcName |
| | } |
| |
|
| | |
| | |
| | |
| | func (p *Profile) Prune(dropRx, keepRx *regexp.Regexp) { |
| | prune := make(map[uint64]bool) |
| | pruneBeneath := make(map[uint64]bool) |
| |
|
| | |
| | |
| | |
| | pruneCache := map[string]bool{} |
| | pruneFromHere := func(s string) bool { |
| | if r, ok := pruneCache[s]; ok { |
| | return r |
| | } |
| | funcName := simplifyFunc(s) |
| | if dropRx.MatchString(funcName) { |
| | if keepRx == nil || !keepRx.MatchString(funcName) { |
| | pruneCache[s] = true |
| | return true |
| | } |
| | } |
| | pruneCache[s] = false |
| | return false |
| | } |
| |
|
| | for _, loc := range p.Location { |
| | var i int |
| | for i = len(loc.Line) - 1; i >= 0; i-- { |
| | if fn := loc.Line[i].Function; fn != nil && fn.Name != "" { |
| | if pruneFromHere(fn.Name) { |
| | break |
| | } |
| | } |
| | } |
| |
|
| | if i >= 0 { |
| | |
| | pruneBeneath[loc.ID] = true |
| |
|
| | |
| | if i == len(loc.Line)-1 { |
| | |
| | prune[loc.ID] = true |
| | } else { |
| | loc.Line = loc.Line[i+1:] |
| | } |
| | } |
| | } |
| |
|
| | |
| | for _, sample := range p.Sample { |
| | |
| | |
| | |
| | foundUser := false |
| | for i := len(sample.Location) - 1; i >= 0; i-- { |
| | id := sample.Location[i].ID |
| | if !prune[id] && !pruneBeneath[id] { |
| | foundUser = true |
| | continue |
| | } |
| | if !foundUser { |
| | continue |
| | } |
| | if prune[id] { |
| | sample.Location = sample.Location[i+1:] |
| | break |
| | } |
| | if pruneBeneath[id] { |
| | sample.Location = sample.Location[i:] |
| | break |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | func (p *Profile) RemoveUninteresting() error { |
| | var keep, drop *regexp.Regexp |
| | var err error |
| |
|
| | if p.DropFrames != "" { |
| | if drop, err = regexp.Compile("^(" + p.DropFrames + ")$"); err != nil { |
| | return fmt.Errorf("failed to compile regexp %s: %v", p.DropFrames, err) |
| | } |
| | if p.KeepFrames != "" { |
| | if keep, err = regexp.Compile("^(" + p.KeepFrames + ")$"); err != nil { |
| | return fmt.Errorf("failed to compile regexp %s: %v", p.KeepFrames, err) |
| | } |
| | } |
| | p.Prune(drop, keep) |
| | } |
| | return nil |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | func (p *Profile) PruneFrom(dropRx *regexp.Regexp) { |
| | pruneBeneath := make(map[uint64]bool) |
| |
|
| | for _, loc := range p.Location { |
| | for i := 0; i < len(loc.Line); i++ { |
| | if fn := loc.Line[i].Function; fn != nil && fn.Name != "" { |
| | funcName := simplifyFunc(fn.Name) |
| | if dropRx.MatchString(funcName) { |
| | |
| | pruneBeneath[loc.ID] = true |
| | loc.Line = loc.Line[i:] |
| | break |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | for _, sample := range p.Sample { |
| | |
| | for i, loc := range sample.Location { |
| | if pruneBeneath[loc.ID] { |
| | sample.Location = sample.Location[i:] |
| | break |
| | } |
| | } |
| | } |
| | } |
| |
|