-
Notifications
You must be signed in to change notification settings - Fork 615
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
Conversation
Codecov Report
@@ 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
Continue to review full report at Codecov.
|
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 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. |
internal/report/source.go
Outdated
// So find the outer-most linenumber in the source file. | ||
frames, err := o.file.SourceLine(an.address + o.base) | ||
found := false | ||
if err == nil { |
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: 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?
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 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 |
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.
Cover the error path?
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 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.
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.
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).
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 the new test code I added is what caused coverage for this code (getSourceFromFile uses the line method).
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 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 { |
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.
Add a test.
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/report/source.go
Outdated
// 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) |
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.
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.
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: had to add a sample program, its binary, and a generated profile.
The change is pretty cool, I forgot to say. |
* Added a sample program, its binary and profile. * Added weblist test based on sample program. * Added test for indentation.
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.
Just a couple more notes.
lines = []string{""} // Skip 0th line | ||
f, err := openSourceFile(path, reader.searchPath) | ||
if err != nil { | ||
reader.errors[path] = err |
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.
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" { |
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.
Should this check for runtime.GOARCH == "amd64"
or is objdump cross-arch enough?
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.
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) |
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.
t.Errorf("indentation(%s): got %d, want %d", c.str, n, c.indent)
, see https://github.com/golang/go/wiki/CodeReviewComments#useful-test-failures
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.
func TestIndentation(t *testing.T) { | ||
for _, c := range []struct { | ||
str string | ||
indent int |
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: wantIndent
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.
busyLoop() | ||
} | ||
|
||
func busyLoop() { |
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.
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.
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.
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.
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.
Agree, it's better to avoid fakes as much as possible.
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.
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.