Skip to content
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

weblist output disassembly now contains inlined source. #235

Merged
merged 4 commits into from
Oct 3, 2017
Merged

weblist output disassembly now contains inlined source. #235

merged 4 commits into from
Oct 3, 2017

Conversation

ghemawat
Copy link
Contributor

In addition, fixed the line number assigned to instructions from inlined calls.

As an illustration, see the before and after output for a "pprof -weblist" command for a simple function:

before
after

Note that in the "before" page, the 7.26 second line cannot be expanded, but in the "after" page clicking on it reveals a wealth of information.

@codecov-io
Copy link

codecov-io commented Sep 28, 2017

Codecov Report

Merging #235 into master will increase coverage by 3.32%.
The diff coverage is 81.25%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #235      +/-   ##
==========================================
+ Coverage   61.71%   65.04%   +3.32%     
==========================================
  Files          34       34              
  Lines        7081     7134      +53     
==========================================
+ Hits         4370     4640     +270     
+ Misses       2326     2093     -233     
- Partials      385      401      +16
Impacted Files Coverage Δ
internal/report/source_html.go 0% <ø> (ø) ⬆️
internal/report/report.go 31.49% <100%> (+9.57%) ⬆️
internal/report/source.go 80.77% <81.05%> (+52.11%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d78d1ea...cfa9ea2. Read the comment docs.

@ghemawat
Copy link
Contributor Author

I am confused by these code coverage reports.

E.g., clicking through to https://codecov.io/gh/google/pprof/pull/235/src/internal/report/report.go, it says that coverage has disappeared for printCallgrind, and showed up for getDisambiguatedNames. Neither of those two functions should have been affected by this PR.

Is the code coverage report actually reliable?

@ghemawat ghemawat closed this Sep 28, 2017
@ghemawat ghemawat reopened this Sep 28, 2017
@aalexand
Copy link
Collaborator

@ghemawat It does look confusing sometimes. E.g. on #236 where I just fixed the test.sh script to strip some redundant tags from the coverage output the coverage changed which I wouldn't expect. I will look more into this.

That said, looking at your report.go link, where does it say the coverage for printCallgrind disappeared? I can see it all read which I think means it's just not covered at all.

@aalexand
Copy link
Collaborator

Similarly for getDisambiguatedNames, I don't think it shows that the function is now covered, it just shows that it used to be covered and covered now. Codecov has a Chrome extension which is useful to overlay the current coverage data over the source in Github:

selection_108

// So find the outer-most linenumber in the source file.
frames, err := o.file.SourceLine(an.address + o.base)
found := false
if err == nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Go style is to limit the scope of variables when possible by putting the assignment within if:

found := false
if frames, err := o.file.SourceLine(an.address + o.base); err == nil {
   ...

Also, should something be done with the error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done w.r.t. scoping.

Error handling: The one other call to SourceLine (in symbolizer.go) treats an error as missing information. I think we should follow the same approach here for graceful degradation in case of missing data.

lines = []string{""} // Skip 0th line
f, err := openSourceFile(path, reader.searchPath)
if err != nil {
reader.errors[path] = err
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cover the error path?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is covered. The error gets remembered in the sourceReader, and then dealt with at the bottom of getSourceFromLine. Added comment to sourceReader struct to explain this better.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant cover in tests. The coverage told the path of remembering the error in reader.errors is not covered. It now says that it's covered (I couldn't see why though).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the new test code I added is what caused coverage for this code (getSourceFromFile uses the line method).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not sure what caused "reader.errors[path] = err" line under the "err != nil" condition to be covered, which is what the coverage says now. The test case provides the source files so my feeling was it shouldn't get into the error handler here. Maybe the coverage info is off.

@@ -529,3 +609,20 @@ func trimPath(path string) string {
}
return path
}

func indentation(line string) int {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// number from F, not from H (which is what Disasm gives us).
//
// So find the outer-most linenumber in the source file.
frames, err := o.file.SourceLine(an.address + o.base)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the diff view in the coverage UI looks like this new code is not covered, apparently because the enclosing function is not covered. Consider adding a test, though feel free to decline because the lack of test seems pre-existing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: had to add a sample program, its binary, and a generated profile.

@aalexand
Copy link
Collaborator

The change is pretty cool, I forgot to say.

Copy link
Collaborator

@aalexand aalexand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple more notes.

lines = []string{""} // Skip 0th line
f, err := openSourceFile(path, reader.searchPath)
if err != nil {
reader.errors[path] = err
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant cover in tests. The coverage told the path of remembering the error in reader.errors is not covered. It now says that it's covered (I couldn't see why though).

)

func TestWebList(t *testing.T) {
if runtime.GOOS != "linux" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this check for runtime.GOARCH == "amd64" or is objdump cross-arch enough?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Extended the conditional.

{" \tfoo", 16},
} {
if n := indentation(c.str); n != c.indent {
t.Errorf("indentation for %v: expect %d, got %d\n", c.str, c.indent, n)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t.Errorf("indentation(%s): got %d, want %d", c.str, n, c.indent), see https://github.com/golang/go/wiki/CodeReviewComments#useful-test-failures

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

func TestIndentation(t *testing.T) {
for _, c := range []struct {
str string
indent int
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: wantIndent

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

busyLoop()
}

func busyLoop() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I am not sure Golang includes the DWARF inline debug information, at least I don't see the inline expansion working with this test case - https://aalexand.github.io/scratch/busyloop.html. We can improve it later I guess.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I could not cause inlining to show up properly in the intermediate data produced by this test. We can add in a C++ binary later that relies on inlining and test its coverage as well.

An alternative would be to use faked out ObjTool, but I think using the real ObjTool gives better confidence that things are working.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, it's better to avoid fakes as much as possible.

@aalexand aalexand merged commit 8494129 into google:master Oct 3, 2017
gmarin13 pushed a commit to gmarin13/pprof that referenced this pull request Dec 17, 2020
weblist output disassembly now contains inlined source.

In addition, fixed the line number assigned to instructions from inlined calls.

As an illustration, see the before and after output for a "pprof -weblist" command for a simple function:

[before](https://ghemawat.github.io/scratch/tmp/list1.html)
[after](https://ghemawat.github.io/scratch/tmp/list2.html)

Note that in the "before" page, the 7.26 second line cannot be expanded, but in the "after" page clicking on it reveals a wealth of information.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants