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

Add a "Merge unaccounted native frames" transform #5141

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mstange
Copy link
Contributor

@mstange mstange commented Sep 26, 2024

Production | Deploy preview

This makes it easier to analyze profiles with JIT frames.

This transform gets rid of 0x12345 frames in the call tree - but only those that haven't been accounted to a shared library, i.e. only frames which we consider to be "probably JIT" frames. This transform does not merge unsymbolicated frames for which we know what library they belong to.

Ideally, we wouldn't have those stray hex addresses in the profiles; either Firefox would filter them out during stack merging, or it should give us the correct memory ranges for JIT functions so that we can account these addresses to the right JS function / JIT trampoline etc. But it's not doing that correctly today.

https://bugzilla.mozilla.org/show_bug.cgi?id=1463559 is one of the bugs about this.

For now it seems easier to just offer a transform which gets rid of these stray JIT address frames. This new transform doesn't really clutter anything up; users will only know about it if they right-click such a frame / call node.

Even if Firefox starts giving us better information for JIT frames, this transform can still be useful. For example, you could see this type of stack frame in profiles that are gathered with samply, on applications that use other JITs or applications which don't have Jitdump instrumentation enabled.
Another use case would be if Firefox uses a system library that makes use of jitting, for example a software OpenGL implementation. Those libraries can't be expected to expose their JIT details to our profiler.

This makes it easier to analyze profiles with JIT frames.

This transform gets rid of 0x12345 frames in the call tree - but only
those that haven't been accounted to a shared library, i.e. only frames
which we consider to be "probably JIT" frames. This transform does not
merge unsymbolicated frames for which we know what library they belong to.

Ideally, we wouldn't have those stray hex addresses in the profiles;
either Firefox would filter them out during stack merging, or it should
give us the correct memory ranges for JIT functions so that we can account
these addresses to the right JS function / JIT trampoline etc.
But it's not doing that correctly today.

https://bugzilla.mozilla.org/show_bug.cgi?id=1463559 is one of the bugs
about this.

For now it seems easier to just offer a transform which gets rid of these
stray JIT address frames. This new transform doesn't really clutter
anything up; users will only know about it if they right-click such a
frame / call node.

Even if Firefox starts giving us better information for JIT frames, this
transform can still be useful. For example, you could see this type of
stack frame in profiles that are gathered with samply, on applications
that use other JITs or applications which don't have Jitdump
instrumentation enabled.
Another use case would be if Firefox uses a system library that makes
use of jitting, for example a software OpenGL implementation. Those
libraries can't be expected to expose their JIT details to our profiler.
@mstange mstange requested a review from canova September 26, 2024 18:35
@mstange mstange self-assigned this Sep 26, 2024
@mstange mstange requested a review from a team as a code owner September 26, 2024 18:35
Copy link
Contributor

@julienw julienw left a comment

Choose a reason for hiding this comment

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

This looks good to me, thanks!

1 thing need to be fixed before landing: implement the shortcut key
Then there's some nitpicking over which shortcut key to use or how to serialize to the URL.
And here and there some comments changes, and some minor refactoring.

@@ -1081,6 +1087,10 @@ TransformNavigator--merge-call-node = Merge Node: { $item }
# $item (String) - Name of the function that transform applied to.
TransformNavigator--merge-function = Merge: { $item }

# "Merge unaccounted native frames" transform.
# See: https://profiler.firefox.com/docs/#/./guide-filtering-call-trees?id=merge
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe the doc could also point to the other l10n key CallNodeContextMenu--transform-merge-unaccounted-native-functions ? @flodolo is there a way to do it? or would you prefer that we copy the doc over there too?

? this.renderTransformMenuItem({
l10nId:
'CallNodeContextMenu--transform-merge-unaccounted-native-functions',
shortcut: 'J',
Copy link
Contributor

Choose a reason for hiding this comment

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

you need to handle this shortcut to handleCallNodeTransformShortcut in actions/profile-view

May I ask why J? I think I'd use "u" or "U" for "unaccounted"?
I guess this may be for "JIT" but because it's not mentioned anywhere it could be difficult to remember.

@@ -91,6 +92,9 @@ const SHORT_KEY_TO_TRANSFORM: { [string]: TransformType } = {};
case 'merge-function':
shortKey = 'mf';
break;
case 'merge-unaccounted-native-functions':
shortKey = 'munfs';
Copy link
Contributor

Choose a reason for hiding this comment

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

(optional) not a super big deal, but what about simply mu or mun?

@@ -859,13 +916,96 @@ export function mergeFunction(
});
}

/**
* Returns a Uint8Array filled with zeros and ones.
* result[funcIndex] === 1 iff isUnaccountedNativeFunction(funcIndex)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit

Suggested change
* result[funcIndex] === 1 iff isUnaccountedNativeFunction(funcIndex)
* result[funcIndex] === 1 if isUnaccountedNativeFunction(funcIndex)

Copy link
Member

Choose a reason for hiding this comment

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

(I think iff (if and only if) makes sense here)

Copy link
Contributor

Choose a reason for hiding this comment

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

oh yeah okay, got it now. All my maths were done in french so I didn't think of that :-)

Comment on lines +929 to +933
if (funcIsJS[i] || funcResource[i] !== -1) {
continue;
}
const locationString = stringTable.getString(funcName[i]);
if (locationString.startsWith('0x')) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think of reusing isUnaccountedNativeFunction?

Comment on lines +956 to +959
// - If the old stack's function is not funcIndexToMerge, then the new stack
// is the same as the old stack.
// - If the old stack's function is funcIndexToMerge, then the new stack is
// the closest ancestor whose func is not funcIndexToMerge, or null if no
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: this comment needs to be updated to replace funcIndexToMerge with something else

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants