angular - 如何识别非常小的 Angular 应用程序中的内存泄漏
问题描述
我目前正在开发一个 Angular 应用程序,该应用程序应该 24/7 运行至少一个月(制造软件)。客户端仅接受每月仅发生一次浏览器重启(维护间隔)。我们实现的第一个用例只包含一个向用户显示一些信息的组件。此时没有用户交互!信息从服务器推送到客户端。目前我只是从服务器轮询数据更新并向用户显示信息。
当前的 200ms 间隔只是为了研究目的,在实际场景中它将是 1000ms。下面的代码导致 Chrome 在 3 小时内增加了大约 40MB 的内存,并且 cpu 使用率增加了高达 50%(消耗两个核心之一)。
推送通知的目标技术是 SignalR。由于我使用 SignalR 发现了内存问题,因此此处提供的轮询实现用于调查 SignalR 库是否是问题所在。不幸的是,我在这里遇到了同样的问题。
当然,每 30 分钟执行一次 window.location.reload() 可以“解决”问题,但这不是一个好的解决方案。如果我在 3 小时后执行重新加载,页面就会崩溃,Chrome 会显示“哦,不……崩溃”。我正在使用 Chrome 73 和 Edge,Edge 的内存增加明显高于 Chrome。使用 Angular 7.2
<div *ngIf="info" style="width: 100%; height: 100%; margin: 0 auto;">
<div class="info status{{ info.Status }}">
<div class="location"><p class="font2">{{ info.Location }}</p></div>
<!-- ... further div elements here but no other *ngIf or *ngFor -->
<div *ngIf="info?.Details" class="no-padding">
<div class="column1 no-padding" *ngFor="let item of info.Details">
<div class="inverse"><p class="font1">{{ item.Name }}</p></div>
</div>
</div>
<img class="icon" src="assets/Icon{{info.Icon}}.png"/>
</div>
</div>
</div>
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription, interval, Subject } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Info } from '../data/info';
@Component({
selector: 'app-info',
templateUrl: './info.component.html',
styleUrls: ['./info.component.scss']
})
export class InfoComponent implements OnInit, OnDestroy {
subscribetimer: Subscription;
subscribelistener: Subscription;
listener: Subject<Info>;
info: Info;
constructor(private http: HttpClient) { }
ngOnInit() {
this.listener = new Subject<Info>();
this.subscribelistener = this.listener.subscribe(unit => this.info = unit);
this.subscribetimer = interval(200)
.subscribe(data => {
this.http.get<Info>(`http://localhost:5000/poll`)
.subscribe(res => this.listener.next(res));
});
}
ngOnDestroy() {
this.subscribetimer.unsubscribe();
this.subscribelistener.unsubscribe();
}
}
我希望我可以 24/7 全天候运行这个小型应用程序至少一个月,而不会出现内存和 CPU 消耗问题。
解决方案
目前尚不清楚泄漏的是什么(以及是否泄漏),因此很难建议一些特别的事情。然而,这里有一些提示:
1)尝试删除不必要Subjects
的,您可以将一个 Observable 暴露info$
给视图:
export class AppComponent {
info$: Observable<IData>;
constructor(private http: HttpClient) { }
ngOnInit() {
this.info$ = interval(200)
.pipe(
exhaustMap(() =>
this.http.get<Info>(`http://localhost:5000/poll`)
)
);
}
}
在视图中,类似于:
<div *ngIf="info$ | async as info">
<div *ngFor="let item of info.items">
{{item}}
</div>
</div>
2)您可能在 http-get 中有大量超时,例如,您的计时器每滴答一次200ms
,而 http-get 可能需要500ms
. exhaustMap
将处理背压,但您应该添加 atimeout
以限制请求时间并肯定添加一些错误处理,因为 http-get 会有错误。一个非常基本的例子:
this.http.get<Info>(`http://localhost:5000/poll`).pipe(
// killing requests taking too long
timeout(400),
// some error handling logic should go here
catchError(error => {
return EMPTY;
})
)
更复杂的方法可能有 atimeout
和 a retry
。
除此之外,http 响应本身可能是错误的或非 json 的,这将导致错误。所以这里的错误处理是必须的。
这是 rxjs 中错误处理的更详细概述。
旁注:您不知道在 24/7 运行一个月时会发生什么。所以你肯定也想在你的系统中添加一些日志记录。只是为了能够学习,如果它失败了。
推荐阅读
- javascript - For 循环不起作用 -> google sheet to google form 自动数据输入
- wagtail - 通过 Snippet 使用 Wagtail Collections for Images,你如何遍历它们以在模板中显示?
- asp.net - ASP.NET 角色如何与授权一起使用?
- node.js - Azure 文件 - 从托管在 Azure 上的我的 Node 应用程序下载无法正常工作
- ms-access - MS Access 合并数字范围
- angular - 在角常春藤的选择中是否可能没有预选条目
- tensorflow - 如何在 keras 中对经常性权重应用 dropConnect
- r - R geom_bar 总和按组计数
- python - 二元分类问题中每个概率截止的准确度(python sklearn准确度)
- c++ - 来自 Visual Studio 中控制台项目的 Exe 文件?