[英]Memory Leak - Garbage Collection in Browser Not Collecting Components
Angular Component Memory Leak - on Chrome and Microsoft Edge (could be all browsers, haven't tested all of them yet) Angular 组件 Memory 泄漏 - 在 Chrome 和 Microsoft Edge 上(可能是所有浏览器,尚未测试所有浏览器)
Sometimes it won't leak memory, sometimes it will.有时不会泄露memory,有时会。 That's what makes this one of the biggest head scratchers I've faced in a while.
这就是使它成为我一段时间以来遇到的最令人头疼的问题之一的原因。
Please don't immediately write this off as "I can't replicate, so it must be fake", if when you first run the program below and it doesn't leak memory. Try it a couple times first, please.如果您第一次运行下面的程序并且它没有泄漏 memory,请不要因为“我无法复制,所以它一定是假的”而立即将其注销。请先尝试几次。 I swear it will eventually get into a state when started (because this bug has been plaguing me for a while), that causes it to leak memory.
我发誓它最终会在启动时进入 state(因为这个错误已经困扰我一段时间),导致它泄漏 memory。
I've narrow it down to this simple app, since this memory leak has been messing with a much larger production app that I've been working on.我已将其缩小到这个简单的应用程序,因为这个 memory 泄漏一直困扰着我一直在开发的一个更大的生产应用程序。
Below is the simplified app that can be used to test with.下面是可用于测试的简化应用程序。
https://github.com/kevinpbaker/angular-memory-killer https://github.com/kevinpbaker/angular-memory-killer
package.json package.json
{
"name": "memory-killer",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve --port 4201",
"build": "ng build --prod --aot --buildOptimizer --commonChunk --vendorChunk --optimization --progress",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~11.2.14",
"@angular/cdk": "^11.2.13",
"@angular/common": "~11.2.14",
"@angular/compiler": "~11.2.14",
"@angular/core": "~11.2.14",
"@angular/forms": "~11.2.14",
"@angular/material": "^11.2.13",
"@angular/platform-browser": "~11.2.14",
"@angular/platform-browser-dynamic": "~11.2.14",
"@angular/router": "~11.2.14",
"rxjs": "~6.5.4",
"rxjs-compat": "^6.5.5",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1102.18",
"@angular/cli": "~11.2.18",
"@angular/compiler-cli": "~11.2.14",
"@angular/language-service": "~11.2.14",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"jasmine-core": "~4.0.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.3.13",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.7.0",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "4.0.8"
}
}
app.module.ts应用程序模块.ts
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {AppComponent, MemoryKiller2Component, MemoryKillerComponent} from './app.component';
@NgModule({
declarations: [
AppComponent,
MemoryKillerComponent,
MemoryKiller2Component
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
index.html index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Memory Killer</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>
app.component.ts应用程序组件.ts
import {Component} from '@angular/core';
import {timer} from 'rxjs';
import {map} from 'rxjs/operators';
@Component({
selector: 'app-root',
template: '<app-memory-killer *ngIf="killCycle$|async"></app-memory-killer>',
})
export class AppComponent {
// change 1000 to 1 if you want to speed up the memory killer
killCycle$ = timer(0, 1000).pipe(map(k => k % 2 !== 0));
}
@Component({
selector: 'app-memory-killer',
template: `
<div class="memory-killer">
<app-memory-killer2></app-memory-killer2>
<app-memory-killer2></app-memory-killer2>
<app-memory-killer2></app-memory-killer2>
</div>
`,
styles: [`.memory-killer { display: flex; }`]
})
export class MemoryKillerComponent { }
@Component({
selector: 'app-memory-killer2',
template: `
<div class="memory-killer2">
<div>Killing your memory</div>
<div>Killing your memory</div>
<div>Killing your memory</div>
</div>
`,
styles: [`.memory-killer2 { display: flex; }`],
})
export class MemoryKiller2Component { }
Microsoft Edge Detached Elements Viewer and Memory Inspector - Version 97.0.1072.55 Microsoft Edge 分离元素查看器和 Memory 检查器 - 版本 97.0.1072.55
Chrome Memory Inspector - Version 97.0.4692.99 Chrome Memory 检查器 - 版本 97.0.4692.99
Visual of DOM Nodes Climbing - You can spam manual garbage collection and it won't collect the components DOM 节点爬升的可视化 - 您可以手动垃圾收集垃圾邮件,但它不会收集组件
Any input as to if this is an angular bug, a browser bug, or if you could point me to the right person that could help me figure this out would be greatly appreciated.任何关于这是 angular 错误、浏览器错误的任何输入,或者如果您能指出可以帮助我解决这个问题的合适人选,我们将不胜感激。
This issue was a browser bug.这个问题是一个浏览器错误。 It has been fixed by the chromium dev team.
它已被 Chromium 开发团队修复。 See the last post within "Original Angular issue post"
请参阅“原始 Angular 问题帖子”中的最后一个帖子
Original Angular issue post: https://github.com/angular/angular/issues/45080原Angular问题贴: https://github.com/angular/angular/issues/45080
Chromium bug specifying fix: https://bugs.chromium.org/p/chromium/issues/detail?id=1308845 Chromium 错误指定修复: https://bugs.chromium.org/p/chromium/issues/detail?id=1308845
This bug has been fixed in Chrome Version M102: See Chromium Bug Report.此错误已在 Chrome 版本 M102 中修复: 请参阅 Chromium 错误报告。
The leak happens because LayoutInline gets added to
TextAutoresizer::fingerprints_
but is never removed.发生泄漏是因为 LayoutInline 被添加到
TextAutoresizer::fingerprints_
但从未被删除。 LayoutBlocks gets removed because it callsTextAutoresizer::Destroy()
fromWillBeDestroyed()
.LayoutBlocks 被移除是因为它从
WillBeDestroyed()
调用TextAutoresizer::Destroy()
) 。 The Oilpanize CL just made the leak bigger because now we retain LayoutObjects pointed byTextAutoresizer::fingerprints_
.Oilpanize CL 只是使泄漏更大,因为现在我们保留了
TextAutoresizer::fingerprints_
指向的 LayoutObjects。The leak detector could not catch this leak because TextAutoresizer is owned by the document so the leak will go away on navigation.
泄漏检测器无法捕获此泄漏,因为 TextAutoresizer 归文档所有,因此泄漏将 go 在导航中消失。
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src/+/3b3305a8d8566a9ba5ef6ccf9d363e6497f06356
以下修订是指此错误: https://chromium.googlesource.com/chromium/src/+/3b3305a8d8566a9ba5ef6ccf9d363e6497f06356
commit 3b3305a8d8566a9ba5ef6ccf9d363e6497f06356 Author: Keishi Hattori keishi@chromium.org Date: Mon Apr 04 23:34:17 2022
commit 3b3305a8d8566a9ba5ef6ccf9d363e6497f06356 作者:Keishi Hattori keishi@chromium.org 日期:2022 年 4 月 4 日星期一 23:34:17
LayoutInline should be removed from
TextAutosizer::FingerprintMapper
LayoutInline 应该从
TextAutosizer::FingerprintMapper
中移除LayoutInline was not removed from
TextAutosizer::FingerprintMapper::fingerprints_
causing a memory leak.LayoutInline 未从
TextAutosizer::FingerprintMapper::fingerprints_
中删除,导致 memory 泄漏。This CL removed LayoutInline from TextAutosizer in
WillBeDestroyed()
.此 CL 从
WillBeDestroyed()
中的 TextAutosizer 中删除了 LayoutInline。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.