Skip to content

Commit e2610de

Browse files
authored
Speed up sliding sync when there are many active subscriptions (#17789)
Two changes: a) use a batch lookup function instead of a loop, b) check existing data to see if we already have what we need and only fetch what we don't.
1 parent e8c8924 commit e2610de

File tree

3 files changed

+63
-7
lines changed

3 files changed

+63
-7
lines changed

changelog.d/17789.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Speed up sliding sync when there are many active subscriptions.

synapse/handlers/sliding_sync/room_lists.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -500,24 +500,28 @@ async def _compute_interested_rooms_new_tables(
500500
# depending on the `required_state` requested (see below).
501501
partial_state_rooms = await self.store.get_partial_rooms()
502502

503+
# Fetch any rooms that we have not already fetched from the database.
504+
subscription_sliding_sync_rooms = (
505+
await self.store.get_sliding_sync_room_for_user_batch(
506+
user_id,
507+
sync_config.room_subscriptions.keys()
508+
- room_membership_for_user_map.keys(),
509+
)
510+
)
511+
room_membership_for_user_map.update(subscription_sliding_sync_rooms)
512+
503513
for (
504514
room_id,
505515
room_subscription,
506516
) in sync_config.room_subscriptions.items():
507517
# Check if we have a membership for the room, but didn't pull it out
508518
# above. This could be e.g. a leave that we don't pull out by
509519
# default.
510-
current_room_entry = (
511-
await self.store.get_sliding_sync_room_for_user(
512-
user_id, room_id
513-
)
514-
)
520+
current_room_entry = room_membership_for_user_map.get(room_id)
515521
if not current_room_entry:
516522
# TODO: Handle rooms the user isn't in.
517523
continue
518524

519-
room_membership_for_user_map[room_id] = current_room_entry
520-
521525
all_rooms.add(room_id)
522526

523527
# Take the superset of the `RoomSyncConfig` for each room.

synapse/storage/databases/main/roommember.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,57 @@ def get_sliding_sync_room_for_user_txn(
14991499
"get_sliding_sync_room_for_user", get_sliding_sync_room_for_user_txn
15001500
)
15011501

1502+
async def get_sliding_sync_room_for_user_batch(
1503+
self, user_id: str, room_ids: StrCollection
1504+
) -> Dict[str, RoomsForUserSlidingSync]:
1505+
"""Get the sliding sync room entry for the given user and rooms."""
1506+
1507+
if not room_ids:
1508+
return {}
1509+
1510+
def get_sliding_sync_room_for_user_batch_txn(
1511+
txn: LoggingTransaction,
1512+
) -> Dict[str, RoomsForUserSlidingSync]:
1513+
clause, args = make_in_list_sql_clause(
1514+
self.database_engine, "m.room_id", room_ids
1515+
)
1516+
sql = f"""
1517+
SELECT m.room_id, m.sender, m.membership, m.membership_event_id,
1518+
r.room_version,
1519+
m.event_instance_name, m.event_stream_ordering,
1520+
m.has_known_state,
1521+
COALESCE(j.room_type, m.room_type),
1522+
COALESCE(j.is_encrypted, m.is_encrypted)
1523+
FROM sliding_sync_membership_snapshots AS m
1524+
INNER JOIN rooms AS r USING (room_id)
1525+
LEFT JOIN sliding_sync_joined_rooms AS j ON (j.room_id = m.room_id AND m.membership = 'join')
1526+
WHERE m.forgotten = 0
1527+
AND {clause}
1528+
AND user_id = ?
1529+
"""
1530+
args.append(user_id)
1531+
txn.execute(sql, args)
1532+
1533+
return {
1534+
row[0]: RoomsForUserSlidingSync(
1535+
room_id=row[0],
1536+
sender=row[1],
1537+
membership=row[2],
1538+
event_id=row[3],
1539+
room_version_id=row[4],
1540+
event_pos=PersistedEventPosition(row[5], row[6]),
1541+
has_known_state=bool(row[7]),
1542+
room_type=row[8],
1543+
is_encrypted=row[9],
1544+
)
1545+
for row in txn
1546+
}
1547+
1548+
return await self.db_pool.runInteraction(
1549+
"get_sliding_sync_room_for_user_batch",
1550+
get_sliding_sync_room_for_user_batch_txn,
1551+
)
1552+
15021553

15031554
class RoomMemberBackgroundUpdateStore(SQLBaseStore):
15041555
def __init__(

0 commit comments

Comments
 (0)