Skip to content

Add JS origin information to flame graph tooltips (Fixes #964)#1000

Merged
mstange merged 4 commits into
firefox-devtools:masterfrom
brisad:js-origin-tooltip
May 31, 2018
Merged

Add JS origin information to flame graph tooltips (Fixes #964)#1000
mstange merged 4 commits into
firefox-devtools:masterfrom
brisad:js-origin-tooltip

Conversation

@brisad

@brisad brisad commented May 11, 2018

Copy link
Copy Markdown
Contributor

This shows the favicon and URL in the tooltip, (or the lib path if it's a native stack frame).

A few changes are introduced in order to make the extended tooltips work.

First, the formatting of the data to display in the tooltip has been removed from the calculation of the flame graph timing data structure. Instead it is done when the tooltip is shown. This speeds up the flame graph considerably since the display data does no need to be unnecessarily created for every box in the flame graph.

Second, the rendering of the favicon uses the NodeIcon component originally under the calltree subdirectory, but has now been moved to the shared directory. Along with this, the class name treeRowIcon is now called nodeIcon.

Third, to stop the tooltip from disappearing when the NodeIcon component asynchronously loads an icon, the clearing of hovered items are yet again modified. Now the hovered item is only cleared when the new hovered item would be something different from the current one.

@brisad brisad requested a review from gregtatum May 11, 2018 19:45
@codecov

codecov Bot commented May 11, 2018

Copy link
Copy Markdown

Codecov Report

Merging #1000 into master will decrease coverage by 0.01%.
The diff coverage is 42.3%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1000      +/-   ##
==========================================
- Coverage   70.89%   70.88%   -0.02%     
==========================================
  Files         141      141              
  Lines        8325     8287      -38     
  Branches     1895     1886       -9     
==========================================
- Hits         5902     5874      -28     
+ Misses       2140     2134       -6     
+ Partials      283      279       -4
Impacted Files Coverage Δ
src/components/calltree/CallTree.js 98.03% <ø> (ø) ⬆️
src/profile-logic/flame-graph.js 100% <ø> (ø) ⬆️
src/components/flame-graph/FlameGraph.js 57.89% <0%> (-3.22%) ⬇️
src/components/flame-graph/Canvas.js 64.94% <0%> (-0.34%) ⬇️
src/components/shared/NodeIcon.js 81.81% <100%> (ø)
src/components/shared/chart/Canvas.js 56.73% <35.29%> (+8.05%) ⬆️
src/profile-logic/call-tree.js 96.22% <80%> (-0.1%) ⬇️
src/profile-logic/gecko-profile-versioning.js 87.01% <0%> (-1.23%) ⬇️
src/actions/receive-profile.js 74.06% <0%> (-0.43%) ⬇️
src/profile-logic/profile-data.js 76.61% <0%> (-0.05%) ⬇️
... and 2 more

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 568aa80...72d87b5. Read the comment docs.

@mstange

mstange commented May 12, 2018

Copy link
Copy Markdown
Contributor

UI-wise this looks great to me. Thanks! I haven't looked at the code much yet.

The only problem I could find during testing is that the tooltip can get very long if the script URL is long, but this is an existing problem that already plagues our other tooltips (I think?) as well as the context menu, so it should probably be fixed in a separate PR. Here's an example.

@brisad

brisad commented May 13, 2018

Copy link
Copy Markdown
Contributor Author

Thanks!

Yes, sounds good to address the long tooltips in a another PR. What would the proper solution be? I think it's too much information in such an URL to be meaningful if we'd just reformat them by adding line breaks. And it would make the context menu look weird. So perhaps just truncate them with an ellipsis?

@mstange

mstange commented May 13, 2018

Copy link
Copy Markdown
Contributor

Truncating with an ellipsis sounds good to me.

@julienw julienw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey Michael,

Great work, this looks good to me. I tried various cases locally (including previous bugs we used to have) and the behavior looks OK.

I left some comments though:

  • potential performance optimizations or correctness
  • placement of the icon

Please tell me if you disagree about anything :)

Comment thread src/components/shared/chart/Canvas.js Outdated

const maybeHoveredItem = this._hoveredItemFromMouseEvent(event);
// These offsets seem to be identical to
// `event.nativeEvent.offsetX/Y`, albeit not recognized by flow.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't like that Flow forces us to use a less performant solution.
You can tell flow using something like this:

_onMouseMove(event: { nativeEvent: MouseEvent } & SyntheticMouseEvent<>) {

I think the order is important, so maybe I'm wrong in the order and { nativeEvent: ... } should come after.

And then you can use offsetX and offsetY directly.

Comment thread src/components/shared/chart/Canvas.js Outdated
pageX: event.pageX,
pageY: event.pageY,
offsetX,
offsetY,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

offsetX and offsetY shouldn't go in the state. Each time you put something in the state this will trigger a rerender, so the rule of thumb is that we shouldn't put in the state something that's not used for render. Here you simply want a local variable (eg: this._offsetX).

In that case this is not a big deal as we change also pageX and pageY that we use at render, so there's no performance issue in this specific case. But I prefer that we use "the right way" as a good example for other similar cases too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh, I missed that; I considered the offsets to be almost the same thing as pageX/Y and thus just put them together in the state. But I agree with you it's better to use the the more correct way.

display: inline-block;
margin-right: 3px;
align-self: flex-end;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It doesn't look very good when the icon is empty:
capture d ecran de 2018-05-14 18-16-28

I think it's not ideal to hide it if there's no favicon because this would make the text "jump". Maybe the best is to put the favicon somewhere else where it's not so awkward when it's absent, so maybe on the right instead of the left. (for LTR languages, but Flex layout does the right thing if we ever make it work for RTL languages anyway).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that doesn't look very good.

But, (ignoring the fact that the icon is too close to the text in the image), putting it on the right side of the text looks a bit off to me:
screenshot from 2018-05-19 23-06-17
I think the favicon goes better together with the domain name of the URL rather than the path on the right side. This exacerbates as the URL gets longer.

Perhaps we can align the URL with the function name above it, then it looks less bad if there's no favicon. What do you think?
screenshot from 2018-05-19 23-28-09

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why not... Counter-proposal though: what do you think of putting it at the top right ? (so at the right of the first line)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Perhaps we can align the URL with the function name above it, then it looks less bad if there's no favicon. What do you think?

This looks pretty good to me and seems like the best option in my opinion.

I don't like the proposal of putting it on the right, probably because favicons are on the left in all other contexts where they're used.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

OK, if @mstange 👍 I'm OK too :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ok, so I pushed new changes that implements the suggested option.
I'm not super pleased with that approach however, mainly because of how it looks when there's no lib/URL at all in the tooltip:
screenshot from 2018-05-26 21-43-59

@julienw 's suggestion to put the whole thing on the top right would solve that problem, but the tooltips tend to be very long if we need to squeeze both function name and URL on the same line.

I'm out of ideas on how to solve this without having text jumping.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't understand - why is there an empty row if neither the favicon nor the url are present?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I was going to answer that it's because the icon has a min-height, but now I realize that I should just add back the conditional rendering of the icon depending on whether displayData.icon is defined. I had removed it, believing it was unnecessary.

Thank you for asking! This shouldn't be problem anymore :)

@brisad brisad force-pushed the js-origin-tooltip branch from 32de133 to 31ce3a2 Compare May 26, 2018 13:08

.flameGraphCanvasTooltip .tooltipTitle {
white-space: nowrap;
overflow: visible;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not adding this will cause tooltips to become truncated with an ellipsis, which is something desirable, but it does it "too much" when displaying tooltips close to the edge of the chart. I'm adding this to retain the current behavior and defer the solution to "too long tooltips"-problem to a separate PR.

@brisad

brisad commented May 26, 2018

Copy link
Copy Markdown
Contributor Author

This is ready for re-review. Please see my comment regarding the problem with tooltips missing lib/URL.

- Use offsetX/Y of nativeEvent directly
- Don't store offsetX/Y as state
- Align url/lib in tooltip better
@brisad brisad force-pushed the js-origin-tooltip branch from 31ce3a2 to ef22a08 Compare May 26, 2018 20:19

@julienw julienw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There's a last nit I'd like, but otherwise this is ready to land :)
Thanks !

Comment thread src/profile-logic/call-tree.js Outdated
displayData = {
...this.getTimingDisplayData(callNodeIndex),
totalTime: `${formatNumber(totalTime)}`,
selfTime: selfTime === 0 ? '—' : `${formatNumber(selfTime)}`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Small nit: We don't need to use a template string here as the the only content is the result of formatNumber. This could be useful if the result of the function wasn't a string, but here it's a string. So you can simply use: totalTime: formatNumber(totalTime) and the same for selfTime.

@mstange mstange merged commit 0cf73b0 into firefox-devtools:master May 31, 2018
@mstange mstange mentioned this pull request Jun 8, 2018
mstange added a commit that referenced this pull request Jun 8, 2018
Deploy latest changes:
#1000 - Add JS origin information to flame graph tooltips (Fixes #964)
#1057 - Don't calculate flame graph timing unnecessarily (Fixes #1050)
#1071 - Move network markers to a separate panel (Fixes #1067)
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