Angular - 动态组件 - 编译器问题 - 内存泄漏?
Angular - Dynamic Component - Compiler Issue - Memory Leak?
我正在尝试创建一个动态组件。 Here is the sample in plunker. http://embed.plnkr.co/EVFglgkp24hkRkpxrEGe/
一切正常,但存在内存泄漏。
Here is the github ticket https://github.com/angular/angular/issues/19997
动态创建的组件正在被销毁,但创建动态组件的组件没有被销毁。换句话说,编译动态组件的组件没有被销毁。
在上面的示例中,如果我们在 "Home" 和 "Dynamic Page" 之间来回导航并拍摄 chrome 中的内存快照,您可以看到这些组件应该是如下图所示,被摧毁的仍然存在。
出于测试目的,我什至尝试评论下面的行,但问题仍然存在。
let injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
let ngMdlRef = ngMdlFac.create(injector);
let cmpFactory = ngMdlRef.componentFactoryResolver.resolveComponentFactory(DynamicHtmlComponent);
this.cmpRef = this.vcRef.createComponent(cmpFactory);
我打电话的那一刻
this.compiler.compileModuleAsync
创建者组件根本没有被销毁。在那之前没有问题。
你能请别人帮忙吗?提前谢谢你。
你是对的,内存泄漏的问题是由手动模块编译和实例化引起的。如果您查看 MyCreatorComponent
的保留器,您会发现函数 DynamicHtmlComponent
和 DynamicModule
通过上下文保存对父 MyCreatorComponent
函数的引用。
这些是距离GC root最近的对象,所以它们很可能是造成内存泄漏的对象。问题是为什么不删除它们?答案是 Angular 大量缓存它创建的所有内容,它也会发生在您的情况下。通过快速浏览,我已经确定至少有两个保留引用的缓存。
第一个
export class JitCompiler {
private _compiledHostTemplateCache = new Map<Type, CompiledTemplate>();
当您调用 this.compiler.compileModuleAsync(DynamicModule)
时,Angular 将 CompiledTemplate
和密钥 DynamicHtmlComponent
添加到此缓存中,并且永远不会清除它。
第二个
const _tokenKeyCache = new Map<any, string>();
当您调用 var ngMdlRef = ngMdlFac.create(...)
时,Angular 将 DynamicHtmlComponentFactory
添加到此缓存中并且永远不会删除它。
请注意,这些缓存是 Maps
,而不是 WeakMaps
,因此只要没有显式调用 .delete()
,对象就会被保留。
我正在尝试创建一个动态组件。 Here is the sample in plunker. http://embed.plnkr.co/EVFglgkp24hkRkpxrEGe/ 一切正常,但存在内存泄漏。
Here is the github ticket https://github.com/angular/angular/issues/19997
动态创建的组件正在被销毁,但创建动态组件的组件没有被销毁。换句话说,编译动态组件的组件没有被销毁。
在上面的示例中,如果我们在 "Home" 和 "Dynamic Page" 之间来回导航并拍摄 chrome 中的内存快照,您可以看到这些组件应该是如下图所示,被摧毁的仍然存在。
出于测试目的,我什至尝试评论下面的行,但问题仍然存在。
let injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
let ngMdlRef = ngMdlFac.create(injector);
let cmpFactory = ngMdlRef.componentFactoryResolver.resolveComponentFactory(DynamicHtmlComponent);
this.cmpRef = this.vcRef.createComponent(cmpFactory);
我打电话的那一刻
this.compiler.compileModuleAsync
创建者组件根本没有被销毁。在那之前没有问题。
你能请别人帮忙吗?提前谢谢你。
你是对的,内存泄漏的问题是由手动模块编译和实例化引起的。如果您查看 MyCreatorComponent
的保留器,您会发现函数 DynamicHtmlComponent
和 DynamicModule
通过上下文保存对父 MyCreatorComponent
函数的引用。
这些是距离GC root最近的对象,所以它们很可能是造成内存泄漏的对象。问题是为什么不删除它们?答案是 Angular 大量缓存它创建的所有内容,它也会发生在您的情况下。通过快速浏览,我已经确定至少有两个保留引用的缓存。
第一个
export class JitCompiler {
private _compiledHostTemplateCache = new Map<Type, CompiledTemplate>();
当您调用 this.compiler.compileModuleAsync(DynamicModule)
时,Angular 将 CompiledTemplate
和密钥 DynamicHtmlComponent
添加到此缓存中,并且永远不会清除它。
第二个
const _tokenKeyCache = new Map<any, string>();
当您调用 var ngMdlRef = ngMdlFac.create(...)
时,Angular 将 DynamicHtmlComponentFactory
添加到此缓存中并且永远不会删除它。
请注意,这些缓存是 Maps
,而不是 WeakMaps
,因此只要没有显式调用 .delete()
,对象就会被保留。