-
Notifications
You must be signed in to change notification settings - Fork 244
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
Support remapping profiles using source maps #317
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
jlfwong
force-pushed
the
jlfwong/source-map
branch
2 times, most recently
from
October 2, 2020 22:06
ddccbbe
to
d493620
Compare
jlfwong
force-pushed
the
jlfwong/source-map
branch
from
October 2, 2020 23:10
d493620
to
e59099d
Compare
jlfwong
changed the title
WIP: Support remapping profiles using source maps
Support remapping profiles using source maps
Oct 3, 2020
Before this lands, I'm going to test on a larger codebase with minification enabled, and also write some tests for |
jlfwong
force-pushed
the
jlfwong/source-map
branch
from
October 13, 2020 00:21
ba9bec3
to
5d7130b
Compare
jlfwong
force-pushed
the
jlfwong/source-map
branch
from
October 13, 2020 00:59
3b19a72
to
a93f600
Compare
Closed
jackerghan
pushed a commit
to jackerghan/speedscope
that referenced
this pull request
Jul 28, 2023
This PR adds the ability to remap an already-loaded profile using a JavaScript source map. This is useful for e.g. recording minified profiles in production, and then remapping their symbols when the source map isn't made directly available to the browser in production. This is a bit of a hidden feature. The way it works is to drop a profile into speedscope, then drop the sourcemap file on top of it. To test this, I used a small project @cricklet made (https://gist.github.com/cricklet/0deaaa7dd63657adb6818f0a52362651), and also tested against speedscope itself. To test against speedscope itself, I profiled loading a file in speedscope in Chrome, then dropped the resulting Chrome timeline profile into speedscope, and dropped speedscope's own sourcemap on top. Before dropping the source map, the symbols look like this: ![image](https://user-images.githubusercontent.com/150329/94977230-b2878f00-04cc-11eb-8907-02a1f1485653.png) After dropping the source map, they look like this: ![image](https://user-images.githubusercontent.com/150329/94977253-d4811180-04cc-11eb-9f88-1e7a02149331.png) I also added automated tests using a small JS bundle constructed with various different JS bundlers to make sure it was doing a sensible thing in each case. # Background Remapping symbols in profiles using source-maps proved to be more complex than I originally thought because of an idiosyncrasy of which line & column are referenced for stack frames in browsers. Rather than the line & column referencing the first character of the symbol, they instead reference the opening paren for the function definition. Here's an example file where it's not immediately apparent which line & column is going to be referenced by each stack frame: ``` class Kludge { constructor() { alpha() } zap() { alpha() } } function alpha() { for (let i = 0; i < 1000; i++) { beta() delta() } } function beta() { for (let i = 0; i < 10; i++) { gamma() } } const delta = function () { for (let i = 0; i < 10; i++) { gamma() } } const gamma = () => { let prod = 1 for (let i = 1; i < 1000; i++) { prod *= i } return prod } const k = new Kludge() k.zap() ``` The resulting profile looks like this: ![image](https://user-images.githubusercontent.com/150329/94976830-0db88200-04cb-11eb-86d7-934365a17c53.png) The relevant line & column for each function are... ``` // Kludge: line 2, column 14 class Kludge { constructor() { ^ ... // zap: line 6, column 6 zap() { ^ ... // alpha: line 11, column 15 function alpha() { ^ ... // delta: line 24, column 24 const delta = function () { ^ ... // gamma: line 31, column 1 const gamma = () => { ^ ``` If we look up the source map entry that corresponds to the opening paren, we'll nearly always get nothing. Instead, we'll look at the entry *preceding* the one which contains the opening paren, and hope that has our symbol name. It seems this works at least some of the time. Another complication is that some, but not all source maps include the original names of functions. For ones that don't, but do include the original source-code, we try to deduce it ourselves with varying amounts of success. Supersedes jlfwong#306 Fixes jlfwong#139
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR adds the ability to remap an already-loaded profile using a JavaScript source map. This is useful for e.g. recording minified profiles in production, and then remapping their symbols when the source map isn't made directly available to the browser in production.
This is a bit of a hidden feature. The way it works is to drop a profile into speedscope, then drop the sourcemap file on top of it.
To test this, I used a small project @cricklet made (https://gist.github.com/cricklet/0deaaa7dd63657adb6818f0a52362651), and also tested against speedscope itself.
To test against speedscope itself, I profiled loading a file in speedscope in Chrome, then dropped the resulting Chrome timeline profile into speedscope, and dropped speedscope's own sourcemap on top. Before dropping the source map, the symbols look like this:
After dropping the source map, they look like this:
I also added automated tests using a small JS bundle constructed with various different JS bundlers to make sure it was doing a sensible thing in each case.
Background
Remapping symbols in profiles using source-maps proved to be more complex than I originally thought because of an idiosyncrasy of which line & column are referenced for stack frames in browsers. Rather than the line & column referencing the first character of the symbol, they instead reference the opening paren for the function definition.
Here's an example file where it's not immediately apparent which line & column is going to be referenced by each stack frame:
The resulting profile looks like this:
The relevant line & column for each function are...
If we look up the source map entry that corresponds to the opening paren, we'll nearly always get nothing. Instead, we'll look at the entry preceding the one which contains the opening paren, and hope that has our symbol name. It seems this works at least some of the time.
Another complication is that some, but not all source maps include the original names of functions. For ones that don't, but do include the original source-code, we try to deduce it ourselves with varying amounts of success.
Supersedes #306
Fixes #139