-
Notifications
You must be signed in to change notification settings - Fork 254
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
Use frame.name?.startsWith
for stackprof
#419
Conversation
This stackprof was generated from https://github.com/sorbet/sorbet by running the sorbet-runtime gem's test suite. This profile itself doesn't exhibit the bug where stackprof sometimes generates profiles with a missing name. Unfortunately, I can only get that to happen when using stackprof at work, where the contents of the profile result contain sensitive file, class, and method names that cannot be shared publically. So instead, I've opted to edit this file to forcibly make it exhibit the bug (see the next commit).
As promised, this frame is going to have it's name deleted to forcibly exhibit the bug.
Sometimes, stackprof frames don't get generated with a `name` in the frame. I think it's probably worth tracking down why that is, but in the mean time, speedscope simply crashes with a method call on `undefined`. The crash is bad because it only shows up in the console--there's no visible message saying that speedscope failed to parse and load a profile. For more information, see jlfwong#378 This fixes the crash by simply skipping the logic in demangle if the name field isn't present on a frame. That's probably a fine tradeoff? Because in this case, stackprof is generating ruby frames, which means that C++ name demangling won't apply. I have tested this by running the scripts/prepare-test-installation.sh script and verifying that `bin/cli.js` can now successfully load the included profile. Before these changes, I verified that speedscope failed with the behavior mentioned in jlfwong#378.
Fixes #378 |
Hi @jez! Thanks for working on fixing this, and including tests no less. I'd prefer to fix this early in the import process, because the It seems to me like the correct fix is to change https://github.com/jlfwong/speedscope/blob/main/src/import/stackprof.ts to ensure that the frame names are present. This would mean updating
I also wonder if this is a bug in stackprof itself that should be fixed upstream |
Thanks for the review, @jlfwong! I picked a slightly different implementation because I was getting a TypeScript error I was not familiar with. (Something about not being able to use |
It probably is! For me it's easier to work around it here in speedscope, because we already have tons and tons of recorded stackprof profiles in our production profiler that I don't really want to have to try to fix—merely upgrading stackprof would only fix the new profiles, and not let me visualize old, already-captured profiles. |
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.
Thanks for adding tests and shifting the change closer to the problem.
Two more changes to land this:
- The change to
profile.ts
needs reverting - I try to keep tests as minimal as possible to make them easy to debug in the future. Large profiles make this more challenging. Is it possible to create a reduced profile? If the nature of doing that is tricky because you aren't sure what triggers the undefined name behaviour, then this is okay as-is
Also FWIW, if you do have a reproduction case for stackprof, would encourage you to report it as a bug on stackprof to prevent others from running into confusing behavior in the future
src/lib/profile.ts
Outdated
@@ -406,7 +406,7 @@ export class Profile { | |||
for (let frame of this.frames) { | |||
// This function converts a mangled C++ name such as "__ZNK7Support6ColorFeqERKS0_" | |||
// into a human-readable symbol (in this case "Support::ColorF::==(Support::ColorF&)") | |||
if (frame.name.startsWith('__Z')) { | |||
if (frame.name?.startsWith('__Z')) { |
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 still needs removing
I did try to reproduce it, but was unable to. I will continue to try to reproduce it, and will report upstream. |
I've updated the test to make it smaller. I just copied the smallest stackprof JSON test and deleted the |
Thanks for the follow through! This will go out with the next release |
This is now live on https://speedscope.app and published to npm as part of v1.15.2. Thanks for your contribution! |
Sometimes, stackprof frames don't get generated with a `name` in the frame. I think it's probably worth tracking down why that is, but in the mean time, speedscope simply crashes with a method call on `undefined`. The crash is bad because it only shows up in the console--there's no visible message saying that speedscope failed to parse and load a profile. For more information, see jlfwong#378 This fixes the crash by simply skipping the logic in demangle if the name field isn't present on a frame. That's probably a fine tradeoff? Because in this case, stackprof is generating ruby frames, which means that C++ name demangling won't apply. I have tested this by running the scripts/prepare-test-installation.sh script and verifying that `bin/cli.js` can now successfully load the included profile. Before these changes, I verified that speedscope failed with the behavior mentioned in jlfwong#378. I've also included a snapshot test case, but it seems that the Jest test harness only tests the parsing, not the rendering (correct me if I'm wrong). So I haven't actually been able to create an automated test that would catch a regression. Please let me know if there's a better way to have written this test. I've staged the commits on this branch so that the second commit (dcb9840) showcases the minimal diff to a stackprof file that reproduces the bug. That is, rather than look at the thousands of new lines in the stackprof profile, you can view the second commit to see the salient part of the file.
Sometimes, stackprof frames don't get generated with a
name
in the frame.I think it's probably worth tracking down why that is, but in the mean
time, speedscope simply crashes with a method call on
undefined
. Thecrash is bad because it only shows up in the console--there's no visible
message saying that speedscope failed to parse and load a profile.
For more information, see #378
This fixes the crash by simply skipping the logic in demangle if the name
field isn't present on a frame. That's probably a fine tradeoff? Because in
this case, stackprof is generating ruby frames, which means that C++ name
demangling won't apply.
I have tested this by running the scripts/prepare-test-installation.sh
script and verifying that
bin/cli.js
can now successfully load theincluded profile. Before these changes, I verified that speedscope failed
with the behavior mentioned in #378.
I've also included a snapshot test case, but it seems that the Jest test
harness only tests the parsing, not the rendering (correct me if I'm wrong).
So I haven't actually been able to create an automated test that would catch
a regression. Please let me know if there's a better way to have written this
test.
I've staged the commits on this branch so that the second commit (dcb9840)
showcases the minimal diff to a stackprof file that reproduces the bug. That is,
rather than look at the thousands of new lines in the stackprof profile, you can
view the second commit to see the salient part of the file.