From 5f3e115545e17c23f4bfdd813fac334cedea7a3d Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 23 Mar 2023 19:02:55 +0000 Subject: [PATCH] Stop doing O(n^2) work to find event's home (#3227) * Stop doing O(n^2) work to find event's home In certain rooms (e.g. with many state changes hidden via user preferences), the events array presented to `eventShouldLiveIn` may contain 100s of events. As part of its various checks, `eventShouldLiveIn` would get an event's associated ID (reply / relation / redaction parent). It would then use `events.find` to search the entire (possibly large) `events` array to look for the parent. (This by itself seems sub-optimal and should probably change to use a map.) For many events in a room, there is no associated ID. Unfortunately, `eventShouldLiveIn` did not check whether the associated ID actually exists before running off to search all of `events`, resulting in O(n^2) work. This changes `eventShouldLiveIn` to first check that there is an associated ID before proceeding with its (slow) search. For some rooms, this change drastically improves performance from ~100% CPU usage to nearly idle. Signed-off-by: J. Ryan Stinnett * Add type to `parentEvent` Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: J. Ryan Stinnett Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- src/models/room.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/models/room.ts b/src/models/room.ts index 399f98614..ca36f67ea 100644 --- a/src/models/room.ts +++ b/src/models/room.ts @@ -2028,8 +2028,11 @@ export class Room extends ReadReceipt { }; } - const parentEventId = event.getAssociatedId()!; - const parentEvent = this.findEventById(parentEventId) ?? events?.find((e) => e.getId() === parentEventId); + const parentEventId = event.getAssociatedId(); + let parentEvent: MatrixEvent | undefined; + if (parentEventId) { + parentEvent = this.findEventById(parentEventId) ?? events?.find((e) => e.getId() === parentEventId); + } // Treat relations and redactions as extensions of their parents so evaluate parentEvent instead if (parentEvent && (event.isRelation() || event.isRedaction())) {