Skip to content

perf(material/tooltip): Defer injection of injectables not needed unt… #30440

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

Merged
merged 1 commit into from
Feb 7, 2025

Conversation

kseamon
Copy link
Collaborator

@kseamon kseamon commented Feb 3, 2025

…il tooltip is shown.

@kseamon kseamon marked this pull request as ready for review February 4, 2025 15:41
@kseamon kseamon requested a review from a team as a code owner February 4, 2025 15:41
@kseamon kseamon requested review from crisbeto and andrewseguin and removed request for a team February 4, 2025 15:41
@@ -187,10 +187,7 @@ const MAX_WIDTH = 200;
},
})
export class MatTooltip implements OnDestroy, AfterViewInit {
private _overlay = inject(Overlay);
Copy link
Member

Choose a reason for hiding this comment

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

Do we know what the impact of this is? These are likely already instantiated by the time the tooltip is rendered.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The impact is to move a small cost (resolving the injectable) from instantiation time to if/when the tooltip is first shown.

The cost should be small enough that it's not noticeable when showing a tooltip, but does add up during instantiation if lots of MatTooltip instances are being created (imagine a big screen full of content that has tooltips).

Further, most MatTooltip instances will be created but not shown, so on net this reduces the cpu burden of MatTooltip, even if only a smidge.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

From an example profiler run:

Of the 15.3ms spent instantiating MatTooltip instances, 8.8ms was spent in calls to inject(). This PR removes 1/3 of the inject calls, so we might naively guess that it saves about 3ms, or almost 1/5 of overall MatTooltip instantiation time.

Copy link
Member

Choose a reason for hiding this comment

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

Is that 15ms per tooltip instance or 15ms for all the instances on the page? I would be hesitant with sprinkling this pattern across the codebase since it makes the component harder to navigate IMO. The tooltip is already a bit messy because of all the manual even bindings.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is across many instances, which is sort of the point.

For the page I'm profiling, a big mat-table, the only Directive/component whose factory/constructor took more time is MatCell (3.3% of table render time), and there are a lot more of those (alas chrome's profiler doesn't give exact numbers). MatTooltip's factory took 1.3%, which is quite significant considering how much else is being rendered.

Note: I separately asked Jeremy and Andrew if I could add a lazy version of inject() to the framework and they suggested keep with this pattern instead for the time being.

Copy link
Member

Choose a reason for hiding this comment

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

Alright, I think it makes sense for commonly used components like MatTooltip, but I don't think that we should apply it everywhere.

@andrewseguin andrewseguin added action: merge The PR is ready for merge by the caretaker target: patch This PR is targeted for the next patch release labels Feb 7, 2025
@andrewseguin andrewseguin merged commit 622152d into angular:main Feb 7, 2025
22 of 24 checks passed
@andrewseguin
Copy link
Contributor

The changes were merged into the following branches: main, 19.1.x

andrewseguin pushed a commit that referenced this pull request Feb 7, 2025
crisbeto added a commit to crisbeto/material2 that referenced this pull request Feb 17, 2025
angular#30440 deferred the injection of some dependencies in the tooltip, including `ViewContainerRef`. This is problematic, because the act of injecting `ViewContainerRef` changes the shape of some internal data structures in the framework's runtime. As a result, hovering over a tooltip that has been hydrated will throw a runtime error because the structure from the server no longer matches the structure on the client.

Fixes angular#30498.
crisbeto added a commit that referenced this pull request Feb 18, 2025
…0500)

#30440 deferred the injection of some dependencies in the tooltip, including `ViewContainerRef`. This is problematic, because the act of injecting `ViewContainerRef` changes the shape of some internal data structures in the framework's runtime. As a result, hovering over a tooltip that has been hydrated will throw a runtime error because the structure from the server no longer matches the structure on the client.

Fixes #30498.
crisbeto added a commit that referenced this pull request Feb 18, 2025
…0500)

#30440 deferred the injection of some dependencies in the tooltip, including `ViewContainerRef`. This is problematic, because the act of injecting `ViewContainerRef` changes the shape of some internal data structures in the framework's runtime. As a result, hovering over a tooltip that has been hydrated will throw a runtime error because the structure from the server no longer matches the structure on the client.

Fixes #30498.

(cherry picked from commit 68b267d)
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Mar 10, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: material/tooltip area: performance Issues related to performance target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants