gpt4 book ai didi

angular - websocket 的严重性能问题 - 每条消息都会触发 Angular 更改检测

转载 作者:行者123 更新时间:2023-12-03 16:15:07 25 4
gpt4 key购买 nike

我有一个 websocket,我目前正在以每秒 45 条左右的速度流式传输消息。在这个级别上,它完全杀死了 Chrome 。浏览器窗口中的所有功能都被锁定。

我已经削减了我的实现,试图找到这个问题的根本原因,怀疑这可能是我处理这些消息的方式存在问题 - 或者在 Angular 中更新/更改检测。

但现在我只剩下我能得到的最简单的 websocket 实现了:

this.socket = new WebSocket('ws://localhost:5000/ws');

let i = 0;
this.socket.onmessage = (e: MessageEvent) => {
i++;
if (i % 100 === 0) {
console.log('recieved' + i);
}
};

这是在 Angular Injectable 中,但它不与任何东西交互。

它每 100 条消息写入控制台。这仍然会以 100% 的 CPU 使用率杀死浏览器,在我停止消息流之前,它甚至大部分时间都不会输出到控制台,然后一切都 catch 了,它会喷出几行“received x00”消息。

消息本身是 JSON,如下所示:
{
"Topic":"2a736d15-a2fe-43b2-8e8b-ee888f15a53a","Type":1,
"Message": {
"Value":2,
"Timestamp":"2017-06-05T14:46:21.615062+01:00"
}
}

它们通常约为 126 个字符。

我假设 websockets 每秒可以处理数万条消息,但我在 google 上找不到任何合理的指标,这听起来像是不合理的性能吗?

我还检查了 CPU 分析器。当一切都被锁定时,它只是一堵巨大的电话墙,所以我将其降低为每秒一条消息:

enter image description here

深入研究这些尖峰之一(每条消息都会发生!): enter image description here

我在其中一个位置设置了一个断点,每当 websocket 被触发时,Angular 似乎都在做某事,这与区域有关(我对此的经验为零!):

堆栈中的第一件事是 Websocket 本身上的 ZoneTask.invoke,但随后 NgZone 被触发,最终调用了一个非常昂贵的更改/更新链:

enter image description here

这一切怎么会发生?订阅 websocket 的 7 行代码完全独立于 Angular 的变更检测,对吧?它们不会更改绑定(bind)到任何组件的任何值。他们唯一的联系是他们坐在 @Injectable() 内的方法中。

最佳答案

Sods law,只要我发布一个问题,我就会找到答案。通常我会删除它,但我找不到太多关于该主题的内容,因此它可能对某人有用。

这是 Zones 的问题。这是 useful blog post .一般来说,Angular 2 使用区域来驱动它的变化检测:

The reason that Angular 2 uses the zone.js is to know when our handler finishes and then the NgZone service (NgZone is a class that wrap the zone service) calls to ApplicationRef.tick() method. The tick() method scans the tree components from top to bottom and calculates in each component the expressions that exist in the template. If the result of the expression is not equal to the previous result, (from the previous tick) Angular will update the DOM property that connects to this expression.



一个简单的单独获得消息性能的简单解决方案是在区域外运行,因此可以使用方便的方法 runOutsideAngular 来检测 angular 的变化。 :
this.zone.runOutsideAngular(() => {
let i = 0;
this.socket.onmessage = (e: MessageEvent) => {
i++;
if (i % 100 === 0) {
console.log('recieved' + i);
}
};
});

关于angular - websocket 的严重性能问题 - 每条消息都会触发 Angular 更改检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44371180/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com