我有一个websocket,我目前以每秒45左右的速度传输消息。在这个级别它完全杀死铬。浏览器窗口中的所有功能都已锁定。
我已经削减了我的实施,试图找到这个问题的根本原因,怀疑这可能是我处理这些消息的方式有些问题 - 或者在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占用率杀死浏览器,它甚至不会在大多数时间输出到控制台,直到我停止消息流,然后一切都赶上并且它喷出几行"收到的x00& #34;消息。
消息本身是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分析器。当外界被锁定时,它只是一大堆通话,所以我将它一秒钟转为一条消息:
我在其中一个位置扔了一个断点,看来Angular在触发websocket时正在做某事,而且它与Zones有关(我没有经验!):< / p>
堆栈中的第一件事是Websocket本身的ZoneTask.invoke,但随后NgZone被触发,最终调用了一个非常昂贵的更改/更新链:
这一切怎么可能发生?订阅websocket的7行代码完全独立于Angular的变更检测权限?他们不会更改绑定到任何组件的任何值。他们唯一的联系是他们坐在@Injectable()
答案 0 :(得分:1)
Sods法律,我一发表问题就找出答案。通常我会删除它,但我找不到关于这个主题的内容,所以它可能对某人有用。
这是Zones的一个问题。这是一个useful blog post。通常,Angular 2使用区域来驱动它的变化检测:
Angular 2使用zone.js的原因是知道我们的处理程序何时完成,然后NgZone服务(NgZone是一个包装区域服务的类)调用ApplicationRef.tick()方法。 tick()方法从上到下扫描树组件,并在每个组件中计算模板中存在的表达式。如果表达式的结果不等于先前的结果,(从上一个tick开始)Angular将更新连接到该表达式的DOM属性。
简单地单独获取消息性能的简单解决方案是在区域外运行,因此使用方便的方法runOutsideAngular
进行角度变化检测:
this.zone.runOutsideAngular(() => {
let i = 0;
this.socket.onmessage = (e: MessageEvent) => {
i++;
if (i % 100 === 0) {
console.log('recieved' + i);
}
};
});