...

Source file src/runtime/pprof/internal/profile/prune.go

     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 location.
    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.DropFrames, 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	}
    98	

View as plain text