内存泄漏 - 浏览器垃圾回收无法收集组件

3

Angular组件内存泄漏 - 在Chrome和Microsoft Edge上(可能所有浏览器,但尚未测试所有浏览器)

  • 我已经在最新版本的Angular 11、12和13上尝试了下面的应用程序,并且已经成功地使它们全部泄漏内存。
  • 当销毁组件时,浏览器没有对Angular组件进行垃圾回收。
  • 组件的浅大小(来自内存检查器)似乎很小,但保留大小(来自内存检查器)很大。
  • DOM节点保留在内存中,导致显着的内存泄漏。
  • 我已经能够让这个程序在Chrome和Edge中造成内存泄漏(尚未尝试其他浏览器)。
  • 它在Angular的开发模式和生产模式下都会发生。
  • 它可能与CSS属性display: flex有关。
  • 我无法在stackblitz上重新创建这个泄漏。我只能在本地运行该应用程序的机器上使其工作。

有时它不会泄漏内存,有时会。这就是为什么这是我最近面临的最大难题之一。

请不要立即将此写成“我无法复制,所以一定是假的”,如果您首次运行以下程序并且它没有泄漏内存,请尝试几次。我发誓它最终会进入一种状态(因为这个bug困扰了我一段时间),导致它泄漏内存。

我已经将其缩小到这个简单的应用程序,因为这个内存泄漏一直在影响我正在工作的一个更大的生产应用程序。

下面是简化版本的应用程序,可用于测试。

https://github.com/kevinpbaker/angular-memory-killer

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

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

<!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

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 分离元素查看器和内存检查器 - 版本 97.0.1072.55

Chrome 内存检查器 - 版本 97.0.4692.99

DOM 节点上升的可视化 - 您可以大量手动进行垃圾回收,但不会回收组件

请问这是 Angular 的 bug 还是浏览器的 bug?还是您能指引我去寻找合适的人来解决这个问题?


这个问题是浏览器的 bug。由 Chromium 开发团队修复了。请参见“原始 Angular 问题帖子”中的最后一篇帖子。

原始 Angular 问题帖子:https://github.com/angular/angular/issues/45080

Chromium 的 bug 具体说明和修复:https://bugs.chromium.org/p/chromium/issues/detail?id=1308845


Chrome的Bug已在https://bugs.chromium.org/p/chromium/issues/detail?id=1308845提交 - 相似问题:在响应模式下使用Angular会出现内存泄漏,或者在Android平板电脑上使用时会出现相同问题 https://stackoverflow.com/questions/71319620/angular-memory-leak-when-using-responsive-mode-or-on-an-android-tablet - Kevin Baker
1个回答

0

Chrome M102 版本已修复此漏洞:请参阅 Chromium Bug 报告.

泄漏发生的原因是LayoutInline被添加到中,但从未被删除。LayoutBlocks被删除,因为它从调用。Oilpanize CL使泄漏变得更大,因为现在我们保留由指向的LayoutObjects。泄漏检测器无法捕获此泄漏,因为TextAutoresizer归文档所有,因此泄漏将在导航时消失。以下修订涉及此错误: https://chromium.googlesource.com/chromium/src/+/3b3305a8d8566a9ba5ef6ccf9d363e6497f06356提交3b3305a8d8566a9ba5ef6ccf9d363e6497f06356作者:Keishi Hattori keishi@chromium.org日期:2022年4月4日23:34:17 LayoutInline应该从中删除。LayoutInline没有从中删除,导致内存泄漏。此CL在中从TextAutosizer中删除了LayoutInline。

2
虽然这个链接可能回答了问题,但最好在这里包含答案的基本部分并提供参考链接。如果链接的页面更改,则仅有链接的答案可能会失效。 - 【来自评论】 - Tobias S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接