-
-
Notifications
You must be signed in to change notification settings - Fork 810
Description
Describe the bug
Hello,
Hi. I'm currently doing some performance tests on ConverseJS. I'm using it in a chat plugin for Peertube (a streaming platform). There are some specific use cases for such platforms, that are not very "standard" in the XMPP world. For example, there can be a lot of users joining at the exact same time (when a live starts). So i have developed some stress tests tools, to find bottlenecks, and to try to fix them.
Currently, i'm evaluating the impact of massive joins, massive nick changes (in my case, users join the room as "Anonymous 12345", then have to change their nickname), then massive leavings.
In this situation, one of the high CPU usage cause is the MUC sidebar rendering. It will be rendered multiple time: when a user joins, when a user change nick, when vcard are downloaded, ...
So, if 100 users joins in a few seconds, the participant list in the sidebar will be rendered continuously, blocking the browser.
I have a fix that seems to help a lot: just use lodash.debounce around the sidebar re-rendering.
Would such fix be welcome in ConverseJS upstream?
I will submit a PR with my fix, and let you decide if you want to merge it or not (if not, i can manually patch, this is not an issue for me).
To Reproduce
Steps to reproduce the behavior:
- Join a room using ConverseJS
- Massively join the room with bots
- See the browser load.
Screenshots
I have some stress test tools. Here are 2 CPU usage graph: one with ConverseJS v10.1.6, one with the fix i suggest.
Note: there are some other tweaking in my code. For example, i hide join/leave notifications, and some nick changes.
In this test scenario, there are 3 key times:
- 100 bots are joining the room
- the 100 bots are changing their nicknames
- the 100 bots are leaving the room
| Before patch | After patch |
|---|---|
![]() |
![]() |
As you can see, there is a much lower CPU usage with the patch (please notice the vertical scale change).
For the record, here is the patch that i applied in the above test:
diff --git a/src/plugins/muc-views/sidebar.js b/src/plugins/muc-views/sidebar.js
index 16688c0..dadf325 100644
--- a/src/plugins/muc-views/sidebar.js
+++ b/src/plugins/muc-views/sidebar.js
@@ -2,7 +2,7 @@ import 'shared/autocomplete/index.js';
import tplMUCSidebar from "./templates/muc-sidebar.js";
import { CustomElement } from 'shared/components/element.js';
import { _converse, api, converse } from "@converse/headless/core";
-
+import debounce from 'lodash-es/debounce.js';
import 'shared/styles/status.scss';
import './styles/muc-occupants.scss';
@@ -19,11 +19,12 @@ export default class MUCSidebar extends CustomElement {
connectedCallback () {
super.connectedCallback();
this.model = _converse.chatboxes.get(this.jid);
- this.listenTo(this.model.occupants, 'add', () => this.requestUpdate());
- this.listenTo(this.model.occupants, 'remove', () => this.requestUpdate());
- this.listenTo(this.model.occupants, 'change', () => this.requestUpdate());
- this.listenTo(this.model.occupants, 'vcard:change', () => this.requestUpdate());
- this.listenTo(this.model.occupants, 'vcard:add', () => this.requestUpdate());
+ const debouncedRequestUpdate = debounce(() => this.requestUpdate(), 200, {maxWait: 1000})
+ this.listenTo(this.model.occupants, 'add', debouncedRequestUpdate);
+ this.listenTo(this.model.occupants, 'remove', debouncedRequestUpdate);
+ this.listenTo(this.model.occupants, 'change', debouncedRequestUpdate);
+ this.listenTo(this.model.occupants, 'vcard:change', debouncedRequestUpdate);
+ this.listenTo(this.model.occupants, 'vcard:add', debouncedRequestUpdate);
this.model.initialized.then(() => this.requestUpdate());
}
