diff options
author | Till <2353100+S7evinK@users.noreply.github.com> | 2023-07-13 14:19:08 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-13 14:19:08 +0200 |
commit | 5267cc0f54db37b8a71a4caa7148e1dff7ae27c1 (patch) | |
tree | 7db7ed3845f1309f1a066a0c7b22aba21f0dd46a /roomserver | |
parent | f12982472c71b8daf3de682c2807989ee695d2cf (diff) |
Optimise getting local members and membership counts (#3150)
The previous version was getting **ALL** membership events (as
`ClientEvents`, so going through `NewEventFromTrustedJSONWithID`) for a
given room.
Now we are querying only locally joined users as `ClientEvents`, which
should **significantly** reduce allocations.
Take for example a large room with 2k membership events, but only 1
local user - avoiding 1999 `NewEventFromTrustedJSONWithID` calls just to
calculate the `roomSize` which we can also query by other means.
This is also getting called for every `OutputRoomEvent` in the userAPI.
Benchmark with 1 local user and 100 remote users.
```
pkg: github.com/matrix-org/dendrite/userapi/consumers
cpu: 12th Gen Intel(R) Core(TM) i5-12500H
│ old.txt │ new.txt │
│ sec/op │ sec/op vs base │
LocalRoomMembers-16 375.9µ ± 7% 327.6µ ± 6% -12.85% (p=0.000 n=10)
│ old.txt │ new.txt │
│ B/op │ B/op vs base │
LocalRoomMembers-16 79.426Ki ± 0% 8.507Ki ± 0% -89.29% (p=0.000 n=10)
│ old.txt │ new.txt │
│ allocs/op │ allocs/op vs base │
LocalRoomMembers-16 1015.0 ± 0% 277.0 ± 0% -72.71% (p=0.000 n=10)
```
Diffstat (limited to 'roomserver')
-rw-r--r-- | roomserver/api/api.go | 1 | ||||
-rw-r--r-- | roomserver/internal/query/query.go | 14 |
2 files changed, 15 insertions, 0 deletions
diff --git a/roomserver/api/api.go b/roomserver/api/api.go index ab56529c..c29406a1 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -227,6 +227,7 @@ type UserRoomserverAPI interface { QueryMembershipsForRoom(ctx context.Context, req *QueryMembershipsForRoomRequest, res *QueryMembershipsForRoomResponse) error PerformAdminEvacuateUser(ctx context.Context, userID string) (affected []string, err error) PerformJoin(ctx context.Context, req *PerformJoinRequest) (roomID string, joinedVia spec.ServerName, err error) + JoinedUserCount(ctx context.Context, roomID string) (int, error) } type FederationRoomserverAPI interface { diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go index 626d3c13..39e3bd0e 100644 --- a/roomserver/internal/query/query.go +++ b/roomserver/internal/query/query.go @@ -974,6 +974,20 @@ func (r *Queryer) LocallyJoinedUsers(ctx context.Context, roomVersion gomatrixse return joinedUsers, nil } +func (r *Queryer) JoinedUserCount(ctx context.Context, roomID string) (int, error) { + info, err := r.DB.RoomInfo(ctx, roomID) + if err != nil { + return 0, err + } + if info == nil { + return 0, nil + } + + // TODO: this can be further optimised by just using a SELECT COUNT query + nids, err := r.DB.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, true, false) + return len(nids), err +} + // nolint:gocyclo func (r *Queryer) QueryRestrictedJoinAllowed(ctx context.Context, roomID spec.RoomID, senderID spec.SenderID) (string, error) { // Look up if we know anything about the room. If it doesn't exist |