-
Notifications
You must be signed in to change notification settings - Fork 612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add show_from profile filter. #372
Conversation
…is implemented as a separate function with it's own test.
…r raw and proto commands. updated the driver test case to match demangled function name. fixed code formatting.
Codecov Report
@@ Coverage Diff @@
## master #372 +/- ##
==========================================
+ Coverage 66.73% 66.88% +0.14%
==========================================
Files 36 36
Lines 7462 7495 +33
==========================================
+ Hits 4980 5013 +33
Misses 2080 2080
Partials 402 402
Continue to review full report at Codecov.
|
internal/driver/commands.go
Outdated
@@ -185,6 +185,10 @@ var pprofVariables = variables{ | |||
"Only show nodes matching regexp", | |||
"If set, only show nodes that match this location.", | |||
"Matching includes the function name, filename or object name.")}, | |||
"show_from": &variable{stringKind, "", "", helpText( | |||
"Drops nodes above the highest matched node of every sample.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd replace "node" with "frame" since the rest of the text uses that. Maybe try to make the description also a bit more like description of prune_from in style since these two are symmetric in a way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
internal/driver/driver.go
Outdated
@@ -193,6 +195,9 @@ func applyCommandOverrides(cmd []string, v variables) variables { | |||
v.set("hide", "") | |||
v.set("show", "") | |||
} | |||
if !showFrom { | |||
v.set("show_from", "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why adding showFrom var and separate check and not just put this line after v.set("show", "")
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure whether to include it in the focus or hide section. it seems those flags are semantically equivalent so i combined focus, hide, and showFrom into a single flag "filter".
internal/driver/driver_test.go
Outdated
@@ -247,6 +248,7 @@ func testSourceURL(port int) string { | |||
|
|||
// solutionFilename returns the name of the solution file for the test | |||
func solutionFilename(source string, f *testFlags) string { | |||
fmt.Printf("solution flags: %v\n", f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug leftover?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup. fixed.
profile/filter.go
Outdated
@@ -74,6 +74,97 @@ func (p *Profile) FilterSamplesByName(focus, ignore, hide, show *regexp.Regexp) | |||
return | |||
} | |||
|
|||
// ShowFrom drops all stack frames before the first match from the root and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: we say "first" here but "highest" in the documentation for the option. I'd try to be consistent in the terminology.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to "highest"
profile/filter.go
Outdated
// returns whether a match was found. If showFrom is nil it returns false and | ||
// does not modify the profile. | ||
// | ||
// Example: consider a sample with frames [A, B, C], where A is the root. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to have example with multiple matches, otherwise you do not demonstrate the "highest" / "first" point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a duplicate B frame to illustrate matching multiple frames.
profile/filter.go
Outdated
showFromLocs := make(map[uint64]bool) | ||
|
||
// Apply to locations. | ||
for _, location := range p.Location { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: location
-> loc
like in other functions in this file, to be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
profile/filter_test.go
Outdated
@@ -392,6 +414,113 @@ func TestFilter(t *testing.T) { | |||
} | |||
} | |||
|
|||
func TestShowFrom(t *testing.T) { | |||
for _, tc := range []struct { | |||
// name is the name of the test case. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and next two comments on the fields are not informative, I'd drop them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
profile/filter_test.go
Outdated
} { | ||
t.Run(tc.name, func(t *testing.T) { | ||
p := tc.profile.Copy() | ||
gotMatch := p.ShowFrom(tc.showFrom) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merge the assignment into the if statement on next line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
profile/filter_test.go
Outdated
gotMatch := p.ShowFrom(tc.showFrom) | ||
|
||
if gotMatch != tc.wantMatch { | ||
t.Errorf("match got %+v want %+v", gotMatch, tc.wantMatch) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comma before "want"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
@@ -392,6 +414,113 @@ func TestFilter(t *testing.T) { | |||
} | |||
} | |||
|
|||
func TestShowFrom(t *testing.T) { | |||
for _, tc := range []struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have test cases that check that "show from" shows frames from the highest match? It is not obvious from the test names that any test does that. Need a test for both locations and lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added two test cases. one for matching multiple frames without inlines, and one with inlines.
PTAL. |
internal/driver/driver.go
Outdated
@@ -150,11 +150,11 @@ func generateReport(p *profile.Profile, cmd []string, vars variables, o *plugin. | |||
} | |||
|
|||
func applyCommandOverrides(cmd []string, v variables) variables { | |||
trim, focus, tagfocus, hide := v["trim"].boolValue(), true, true, true | |||
trim, tagfocus, filter := v["trim"].boolValue(), true, true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename "tagfocus" to "tagfilter", I think it will be clearer, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
profile/filter.go
Outdated
// filterShowFromLocation tests a showFrom regex against a location, removes | ||
// lines after the last match and returns whether a match was found. If the | ||
// mapping is matched, then all lines are kept. | ||
func filterShowFromLocation(loc *Location, showFrom *regexp.Regexp) (matched bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think named return parameter doesn't give here much. I'd just return a bool and then do "return true" and return false" as needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
profile/filter.go
Outdated
} | ||
if i := loc.lastMatchedLineIndex(showFrom); i >= 0 { | ||
matched = true | ||
loc.Line = loc.Line[0 : i+1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: specifying zero is not required: loc.Line[:i+1]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
@lvng Could you also include the new flag in the docs in https://github.com/google/pprof/tree/master/doc#options? |
doc/README.md
Outdated
@@ -94,6 +94,8 @@ Some common pprof options are: | |||
*regex*. | |||
* **-ignore= _regex_:** Do not include samples that include a report entry matching | |||
*regex*. | |||
* **-show\_from= _regex_:** Do not show entries above the first frame that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe say "above the first one" as it doesn't look like the text here uses term "frame".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
* 'master' of github.com:google/pprof: (32 commits) record diff base profile label key/value constant (google#384) apply additional command overrides based on report format (google#381) profile: fix legacy format Go heap profile parsing (google#382) add -diff flag for better profile comparision (google#369) Use -u flag in pprof installation command so that it updates if needed. (google#376) Add GetBase support for ASLR kernel mappings (google#371) Add show_from profile filter. (google#372) Update README.md due to 8dff45d (google#375) Remove stale docs, move useful ones. (google#374) internal/driver: skip tests requiring tcp on js (google#373) Add "trim path" option which can be used to relocate sources. (google#366) Move update_d3flamegraph.sh script from the root directory. (google#370) Skip unsymbolizable mapping during symbolz pass. (google#368) remove -positive_percentages flag (google#365) Render icicle graph in "Flame Graph" view (google#367) Add command-line editing support for interactive pprof (google#362) Improve profile filter unit tests, fix show filtering of mappings (google#354) Fake mappings should be merged into a single one during merging (google#357) Hack the code so that both existing Go versions and current Go master format it the same (google#358) moved filter tests into their own test file which matches the implementation file, filter.go. (google#356) ...
This change adds the show_from filter, which drops frames before the first match in each stack, beginning from the root.
This fixes #363.