1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2026-01-03 23:22:30 +03:00

Change calculating display names from O(n^2) to O(n)

Reduces initial sync times from ~30s to ~1s on accounts with heavily
populated rooms.

The problem was that f.e. RoomMember it would try to calculate the
display name, which involved looping each RoomMember to get their
display name to check for disambiguation. We now cache display names
to user IDs so we don't need to loop every member when disambiguating.
This commit is contained in:
Kegan Dougal
2015-10-21 13:25:23 +01:00
parent d7c63e3487
commit cab7a71a94
3 changed files with 41 additions and 10 deletions

View File

@@ -208,18 +208,13 @@ function calculateDisplayName(member, event, roomState) {
return displayName;
}
var stateEvents = utils.filter(
roomState.getStateEvents("m.room.member"),
function(e) {
return e.getContent().displayname === displayName &&
e.getSender() !== selfUserId;
}
);
if (stateEvents.length > 0) {
// need to disambiguate
var userIds = roomState.getUserIdsWithDisplayName(displayName);
var otherUsers = userIds.filter(function(u) {
return u !== selfUserId;
});
if (otherUsers.length > 0) {
return displayName + " (" + selfUserId + ")";
}
return displayName;
}

View File

@@ -31,6 +31,8 @@ function RoomState(roomId) {
// userId: RoomMember
};
this._updateModifiedTime();
this._displayNameToUserIds = {};
this._userIdsToDisplayNames = {};
}
utils.inherits(RoomState, EventEmitter);
@@ -108,6 +110,11 @@ RoomState.prototype.setStateEvents = function(stateEvents) {
self.events[event.getType()] = {};
}
self.events[event.getType()][event.getStateKey()] = event;
if (event.getType() === "m.room.member") {
_updateDisplayNameCache(
self, event.getStateKey(), event.getContent().displayname
);
}
self.emit("RoomState.events", event, self);
});
@@ -180,11 +187,37 @@ RoomState.prototype.getLastModifiedTime = function() {
return this._modified;
};
RoomState.prototype.getUserIdsWithDisplayName = function(displayName) {
return this._displayNameToUserIds[displayName] || [];
};
/**
* The RoomState class.
*/
module.exports = RoomState;
function _updateDisplayNameCache(roomState, userId, displayName) {
var oldName = roomState._userIdsToDisplayNames[userId];
delete roomState._userIdsToDisplayNames[userId];
if (oldName) {
var existing = roomState._displayNameToUserIds[oldName] || [];
for (var i = 0; i < existing.length; i++) {
if (existing[i] === userId) {
existing.splice(i, 1);
i--;
}
}
roomState._displayNameToUserIds[oldName] = existing;
}
roomState._userIdsToDisplayNames[userId] = displayName;
if (!roomState._displayNameToUserIds[displayName]) {
roomState._displayNameToUserIds[displayName] = [];
}
roomState._displayNameToUserIds[displayName].push(userId);
}
/**
* Fires whenever the event dictionary in room state is updated.
* @event module:client~MatrixClient#"RoomState.events"

View File

@@ -201,6 +201,9 @@ describe("RoomMember", function() {
}),
joinEvent
];
},
getUserIdsWithDisplayName: function(displayName) {
return [userA, userC];
}
};
expect(member.name).toEqual(userA); // default = user_id