// Copyright 2014 Google Inc. All Rights Reserved.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// Implements methods to remove frames from profiles.package profileimport ()var ( reservedNames = []string{"(anonymous namespace)", "operator()"} bracketRx = func() *regexp.Regexp {var []stringfor , := rangeappend(reservedNames, "(") { = append(, regexp.QuoteMeta()) }returnregexp.MustCompile(strings.Join(, "|")) }())// simplifyFunc does some primitive simplification of function names.func simplifyFunc( string) string {// Account for leading '.' on the PPC ELF v1 ABI. := strings.TrimPrefix(, ".")// Account for unsimplified names -- try to remove the argument list by trimming // starting from the first '(', but skipping reserved names that have '('.for , := rangebracketRx.FindAllStringSubmatchIndex(, -1) { := falsefor , := rangereservedNames {if [[0]:[1]] == { = truebreak } }if ! { = [:[0]]break } }return}// Prune removes all nodes beneath a node matching dropRx, and not// matching keepRx. If the root node of a Sample matches, the sample// will have an empty stack.func ( *Profile) (, *regexp.Regexp) { := make(map[uint64]bool) := make(map[uint64]bool)// simplifyFunc can be expensive, so cache results. // Note that the same function name can be encountered many times due // different lines and addresses in the same function. := map[string]bool{} // Map from function to whether or not to prune := func( string) bool {if , := []; {return } := simplifyFunc()if .MatchString() {if == nil || !.MatchString() { [] = truereturntrue } } [] = falsereturnfalse }for , := range .Location {varintfor = len(.Line) - 1; >= 0; -- {if := .Line[].Function; != nil && .Name != "" {if (.Name) {break } } }if >= 0 {// Found matching entry to prune. [.ID] = true// Remove the matching location.if == len(.Line)-1 {// Matched the top entry: prune the whole location. [.ID] = true } else { .Line = .Line[+1:] } } }// Prune locs from each Samplefor , := range .Sample {// Scan from the root to the leaves to find the prune location. // Do not prune frames before the first user frame, to avoid // pruning everything. := falsefor := len(.Location) - 1; >= 0; -- { := .Location[].IDif ![] && ![] { = truecontinue }if ! {continue }if [] { .Location = .Location[+1:]break }if [] { .Location = .Location[:]break } } }}// RemoveUninteresting prunes and elides profiles using built-in// tables of uninteresting function names.func ( *Profile) () error {var , *regexp.Regexpvarerrorif .DropFrames != "" {if , = regexp.Compile("^(" + .DropFrames + ")$"); != nil {returnfmt.Errorf("failed to compile regexp %s: %v", .DropFrames, ) }if .KeepFrames != "" {if , = regexp.Compile("^(" + .KeepFrames + ")$"); != nil {returnfmt.Errorf("failed to compile regexp %s: %v", .KeepFrames, ) } } .Prune(, ) }returnnil}// PruneFrom removes all nodes beneath the lowest node matching dropRx, not including itself.//// Please see the example below to understand this method as well as// the difference from Prune method.//// A sample contains Location of [A,B,C,B,D] where D is the top frame and there's no inline.//// PruneFrom(A) returns [A,B,C,B,D] because there's no node beneath A.// Prune(A, nil) returns [B,C,B,D] by removing A itself.//// PruneFrom(B) returns [B,C,B,D] by removing all nodes beneath the first B when scanning from the bottom.// Prune(B, nil) returns [D] because a matching node is found by scanning from the root.func ( *Profile) ( *regexp.Regexp) { := make(map[uint64]bool)for , := range .Location {for := 0; < len(.Line); ++ {if := .Line[].Function; != nil && .Name != "" { := simplifyFunc(.Name)if .MatchString() {// Found matching entry to prune. [.ID] = true .Line = .Line[:]break } } } }// Prune locs from each Samplefor , := range .Sample {// Scan from the bottom leaf to the root to find the prune location.for , := range .Location {if [.ID] { .Location = .Location[:]break } } }}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.