Ivy doesn’t deallocate memory of destroyed components correctly
See original GitHub issue🐞 bug report
Affected Package
The issue is caused by package @angular/core@9.0.0-rc.14, earlier versions probably as well.
Is this a regression?
This issue does not occur in Angular 8 + View Engine.
Description
Ivy does not seem to correctly deallocate memory of destroyed components in all cases. We’ve noticed an issue that when navigating away from a route, at least some of the loaded components are getting destroyed but not deallocated and garbage collected. (The issue might not be restricted to routing.)
The problem is that unnecessary memory is not deallocated, which might lead to problems on mobile and other low-memory devices and might also have security implications (e.g. when sensitive state remains in memory, even after a user has logged out).
🔬 Minimal Reproduction
Here is a minimal repo of the problem. It’s a plain Angular CLI application with three routes and four components:
/#/route1
(Route1Component
) includes theContentComponent
as a child that loads the contents of a large file retrieved via the network into a field of its class duringngOnInit
, consuming some memory. This component logs to the console when it’s being initialized or destroyed./#/route2
(Route2Component
) androute3
(Route3Component
) don’t include this component.
Repro steps:
git clone https://github.com/thinktecture-labs/ivy-mem-leak.git
cd ivy-mem-leak
npm i
npm start
- Open http://localhost:4200/#/route3
- Open Chrome dev tools > Memory
- Click 🔴 Take Heap Snapshot
- Open http://localhost:4200/#/route2
- Take a snapshot (size should stay roughly the same)
- Open http://localhost:4200/#/route1, wait until the large file has been downloaded (check the Network tab)
- Take a snapshot (size should be larger than before)
- Open http://localhost:4200/#/route2
- Take a snapshot (size should not significantly change, even though the
ContentComponent
was destroyed, check the Console tab)
Stop ng serve
and compare this with the behavior of Angular 8:
git checkout ng8
npm i
npm start
- Click 🚫 Clear All Profiles
- Open http://localhost:4200/#/route3
- Take a snapshot
- Open http://localhost:4200/#/route2
- Take a snapshot (size should stay roughly the same)
- Open http://localhost:4200/#/route1
- Take a snapshot (should be larger than before)
- Open http://localhost:4200/#/route2
- Take a snapshot (should be similar to the first two snapshots again)
🔥 Exception or Error
The memory of route1
’s components doesn’t seem to be correctly deallocated when leaving route1
for route2
on Angular 9/Ivy:
Angular 9/Ivy | Angular 8/View Engine |
---|---|
![]() |
![]() |
As per DevTools, (at least) the component instance of the ContentComponent
seems to be retained by a contextLView
array even after it has been destroyed:
Is this behavior intended or is this a bug?
Researched by @ManuelRauber, @thomashilzendegen and me.
🌍 Your Environment
Angular Version:
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 9.0.0-rc.12
Node: 12.14.1
OS: darwin x64
Angular: 9.0.0-rc.14
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.900.0-rc.12
@angular-devkit/build-angular 0.900.0-rc.12
@angular-devkit/build-optimizer 0.900.0-rc.12
@angular-devkit/build-webpack 0.900.0-rc.12
@angular-devkit/core 9.0.0-rc.12
@angular-devkit/schematics 9.0.0-rc.12
@angular/cli 9.0.0-rc.12
@ngtools/webpack 9.0.0-rc.12
@schematics/angular 9.0.0-rc.12
@schematics/update 0.900.0-rc.12
rxjs 6.5.4
typescript 3.7.5
webpack 4.41.2
Anything else relevant?
—
Issue Analytics
- State:
- Created 4 years ago
- Reactions:11
- Comments:6 (4 by maintainers)
Kudos for such a well documented repro steps. I wish more people would provide examples such as these.
It looks to me that
master
is also on Ivy and when I try to reproduce the working example it also retains onmaster
could you please fix that?no need to do anything.