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

perf(core): avoid storing LView in __ngContext__ #41358

Closed
wants to merge 9 commits into from

Conversation

crisbeto
Copy link
Member

@crisbeto crisbeto commented Mar 28, 2021

Currently we save a reference to an LView on most DOM nodes created by Angular either by saving the LView directly in the __ngContext__ or by saving the LContext which has a reference to the LView. This can be a problem if the DOM node is retained in memory, because the LView has references to all of the child nodes of the view, as well as other internal data structures.

Previously we tried to resolve the issue by clearing the __ngContext__ when a node is removed (see #36011), but we decided not to proceeed, because it can slow down destruction due to a megamorphic write.

These changes aim to address the issue while reducing the performance impact by assigning a unique ID when an LView is created and adding it to __ngContext__. All active views are tracked in a map where their unique ID is used as the key. We don't need to worry about leaks within that map, because LViews are an internal data structure and we have complete control over when they are created and destroyed.

Fixes #41047.

@crisbeto crisbeto requested a review from mhevery March 28, 2021 11:16
@crisbeto crisbeto added action: review The PR is still awaiting reviews from at least one requested reviewer area: core Issues related to the framework runtime target: major This PR is targeted for the next major release labels Mar 28, 2021
@ngbot ngbot bot modified the milestone: Backlog Mar 28, 2021
@crisbeto crisbeto marked this pull request as ready for review March 28, 2021 11:16
@crisbeto crisbeto force-pushed the ng-context branch 2 times, most recently from 7038e66 to 59a47d5 Compare March 29, 2021 18:21
@crisbeto crisbeto force-pushed the ng-context branch 2 times, most recently from 816eeef to c2c32e2 Compare March 29, 2021 18:47
@crisbeto
Copy link
Member Author

crisbeto commented Mar 29, 2021

All of the feedback should be addressed now.

Copy link
Contributor

@AndrewKushnir AndrewKushnir left a comment

Choose a reason for hiding this comment

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

Thanks for the changes @crisbeto 👍 Just left a few comments.

One more nit: should we change the fix(core) -> refactor(core) or perf(core)? It looks like this is more of an improvement vs a bug fix.

packages/core/src/debug/debug_node.ts Outdated Show resolved Hide resolved
packages/core/src/render3/context_discovery.ts Outdated Show resolved Hide resolved
packages/core/src/render3/context_discovery.ts Outdated Show resolved Hide resolved
packages/core/src/render3/context_discovery.ts Outdated Show resolved Hide resolved
packages/core/src/render3/instructions/lview_tracking.ts Outdated Show resolved Hide resolved
packages/core/src/render3/util/discovery_utils.ts Outdated Show resolved Hide resolved
packages/core/src/render3/util/discovery_utils.ts Outdated Show resolved Hide resolved
packages/core/src/render3/util/discovery_utils.ts Outdated Show resolved Hide resolved
Copy link
Member

@mgechev mgechev left a comment

Choose a reason for hiding this comment

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

The change will break DevTools. Exporting getLViewById will be helpful to let our metadata collection mechanism fallback to the new approach.

@crisbeto crisbeto changed the title fix(core): avoid storing LView in __ngContext__ perf(core): avoid storing LView in __ngContext__ Mar 30, 2021
@crisbeto crisbeto force-pushed the ng-context branch 5 times, most recently from 83bf66c to 186f79d Compare March 30, 2021 11:05
Copy link
Contributor

@AndrewKushnir AndrewKushnir left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for addressing the feedback @crisbeto 👍

FYI, I'm adding the "blocked" label for now to make sure we unblock Minko (based on his comment) before merging.

packages/core/src/debug/debug_node.ts Outdated Show resolved Hide resolved
packages/core/src/debug/debug_node.ts Outdated Show resolved Hide resolved
packages/core/src/render3/context_discovery.ts Outdated Show resolved Hide resolved
@crisbeto crisbeto force-pushed the ng-context branch 3 times, most recently from c8d56c2 to 68478a4 Compare April 22, 2021 19:22
@crisbeto
Copy link
Member Author

I've pushed another change to account for the recent switch from loadLContext to getLContext.

Copy link
Contributor

@AndrewKushnir AndrewKushnir left a comment

Choose a reason for hiding this comment

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

@crisbeto thanks for applying fixes and rebasing the PR! 👍
I've left a couple comments (mostly around the areas that might potentially have null where we extract lView from the context).

packages/core/src/render3/util/discovery_utils.ts Outdated Show resolved Hide resolved
packages/core/src/render3/util/discovery_utils.ts Outdated Show resolved Hide resolved
packages/core/src/render3/util/discovery_utils.ts Outdated Show resolved Hide resolved
packages/core/src/render3/util/discovery_utils.ts Outdated Show resolved Hide resolved
Copy link
Member Author

@crisbeto crisbeto left a comment

Choose a reason for hiding this comment

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

I've addressed the latest set of feedback.

packages/core/src/render3/util/discovery_utils.ts Outdated Show resolved Hide resolved
packages/core/src/render3/util/discovery_utils.ts Outdated Show resolved Hide resolved
packages/core/src/render3/util/discovery_utils.ts Outdated Show resolved Hide resolved
@AndrewKushnir
Copy link
Contributor

Presubmit.

@AndrewKushnir
Copy link
Contributor

FYI presubmits went well, I'll run a global one during the weekend (to make sure there are no corner-cases that we've not reviewed/discussed) and I will share results on Monday.

@AndrewKushnir
Copy link
Contributor

@AndrewKushnir
Copy link
Contributor

FYI, global presubmit went well too, removing the "presubmit" label.

@AndrewKushnir AndrewKushnir removed the action: presubmit The PR is in need of a google3 presubmit label Apr 26, 2021
@crisbeto crisbeto added the action: merge The PR is ready for merge by the caretaker label Apr 26, 2021
jessicajaniuk pushed a commit that referenced this pull request Apr 26, 2021
Currently we save a reference to an `LView` on most DOM nodes created by Angular either by saving
the `LView` directly in the `__ngContext__` or by saving the `LContext` which has a reference to
the `LView`. This can be a problem if the DOM node is retained in memory, because the `LView` has
references to all of the child nodes of the view, as well as other internal data structures.

Previously we tried to resolve the issue by clearing the `__ngContext__` when a node is removed
(see #36011), but we decided not to proceeed, because it can
slow down destruction due to a megamorphic write.

These changes aim to address the issue while reducing the performance impact by assigning a unique
ID when an `LView` is created and adding it to `__ngContext__`. All active views are tracked in
a map where their unique ID is used as the key. We don't need to worry about leaks within that map,
because `LView`s are an internal data structure and we have complete control over when they are
created and destroyed.

Fixes #41047.

PR Close #41358
crisbeto added a commit to crisbeto/angular that referenced this pull request Apr 30, 2021
This is a follow-up to angular#41358 where my assumption was that `destroyLView` would be called for all views down the tree, but it turns out that it only gets called for the root and we actually call `cleanUpView` for the descendants. The result is that some views might not be removed from the registry after they're destroyed.

These changes move the `unregisterLView` call into `cleanUpView` instead.
crisbeto added a commit to crisbeto/angular that referenced this pull request Apr 30, 2021
crisbeto added a commit to crisbeto/angular that referenced this pull request Apr 30, 2021
satanTime added a commit to help-me-mom/ng-mocks that referenced this pull request Apr 30, 2021
mhevery pushed a commit that referenced this pull request Apr 30, 2021
mhevery pushed a commit that referenced this pull request Apr 30, 2021
crisbeto added a commit to crisbeto/angular that referenced this pull request Apr 30, 2021
These changes combine angular#41358 and angular#41894.

Currently we save a reference to an `LView` on most DOM nodes created by Angular either by saving the `LView` directly in the `__ngContext__` or by saving the `LContext` which has a reference to the `LView`. This can be a problem if the DOM node is retained in memory, because the `LView` has references to all of the child nodes of the view, as well as other internal data structures.

Previously we tried to resolve the issue by clearing the `__ngContext__` when a node is removed (see angular#36011), but we decided not to proceeed, because it can slow down destruction due to a megamorphic write.

These changes aim to address the issue while reducing the performance impact by assigning a unique ID when an `LView` is created and adding it to `__ngContext__`. All active views are tracked in a map where their unique ID is used as the key. We don't need to worry about leaks within that map,  because `LView`s are an internal data structure and we have complete control over when they are  created and destroyed.

Fixes angular#41047.
@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 May 27, 2021
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: core Issues related to the framework runtime cla: yes target: rc This PR is targeted for the next release-candidate
Projects
None yet
Development

Successfully merging this pull request may close these issues.

__ngContext__ magnifies native Chrome memory leaks
8 participants