OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. |
| 4 |
| 5 // Implements methods to remove frames from profiles. |
| 6 |
| 7 package profile |
| 8 |
| 9 import ( |
| 10 "fmt" |
| 11 "regexp" |
| 12 ) |
| 13 |
| 14 // Prune removes all nodes beneath a node matching dropRx, and not |
| 15 // matching keepRx. If the root node of a Sample matches, the sample |
| 16 // will have an empty stack. |
| 17 func (p *Profile) Prune(dropRx, keepRx *regexp.Regexp) { |
| 18 prune := make(map[uint64]bool) |
| 19 pruneBeneath := make(map[uint64]bool) |
| 20 |
| 21 for _, loc := range p.Location { |
| 22 var i int |
| 23 for i = len(loc.Line) - 1; i >= 0; i-- { |
| 24 if fn := loc.Line[i].Function; fn != nil && fn.Name != "
" { |
| 25 funcName := fn.Name |
| 26 // Account for leading '.' on the PPC ELF v1 ABI
. |
| 27 if funcName[0] == '.' { |
| 28 funcName = funcName[1:] |
| 29 } |
| 30 if dropRx.MatchString(funcName) { |
| 31 if keepRx == nil || !keepRx.MatchString(
funcName) { |
| 32 break |
| 33 } |
| 34 } |
| 35 } |
| 36 } |
| 37 |
| 38 if i >= 0 { |
| 39 // Found matching entry to prune. |
| 40 pruneBeneath[loc.ID] = true |
| 41 |
| 42 // Remove the matching location. |
| 43 if i == len(loc.Line)-1 { |
| 44 // Matched the top entry: prune the whole locati
on. |
| 45 prune[loc.ID] = true |
| 46 } else { |
| 47 loc.Line = loc.Line[i+1:] |
| 48 } |
| 49 } |
| 50 } |
| 51 |
| 52 // Prune locs from each Sample |
| 53 for _, sample := range p.Sample { |
| 54 // Scan from the root to the leaves to find the prune location. |
| 55 // Do not prune frames before the first user frame, to avoid |
| 56 // pruning everything. |
| 57 foundUser := false |
| 58 for i := len(sample.Location) - 1; i >= 0; i-- { |
| 59 id := sample.Location[i].ID |
| 60 if !prune[id] && !pruneBeneath[id] { |
| 61 foundUser = true |
| 62 continue |
| 63 } |
| 64 if !foundUser { |
| 65 continue |
| 66 } |
| 67 if prune[id] { |
| 68 sample.Location = sample.Location[i+1:] |
| 69 break |
| 70 } |
| 71 if pruneBeneath[id] { |
| 72 sample.Location = sample.Location[i:] |
| 73 break |
| 74 } |
| 75 } |
| 76 } |
| 77 } |
| 78 |
| 79 // RemoveUninteresting prunes and elides profiles using built-in |
| 80 // tables of uninteresting function names. |
| 81 func (p *Profile) RemoveUninteresting() error { |
| 82 var keep, drop *regexp.Regexp |
| 83 var err error |
| 84 |
| 85 if p.DropFrames != "" { |
| 86 if drop, err = regexp.Compile("^(" + p.DropFrames + ")$"); err !
= nil { |
| 87 return fmt.Errorf("failed to compile regexp %s: %v", p.D
ropFrames, err) |
| 88 } |
| 89 if p.KeepFrames != "" { |
| 90 if keep, err = regexp.Compile("^(" + p.KeepFrames + ")$"
); err != nil { |
| 91 return fmt.Errorf("failed to compile regexp %s:
%v", p.KeepFrames, err) |
| 92 } |
| 93 } |
| 94 p.Prune(drop, keep) |
| 95 } |
| 96 return nil |
| 97 } |
OLD | NEW |