mirror of
				https://github.com/matrix-org/synapse.git
				synced 2025-11-03 21:57:26 +00:00 
			
		
		
		
	Skip unused calculations in sync handler. (#14908)
If a sync request does not need to calculate per-room entries & is not generating presence & is not generating device list data (e.g. during initial sync) avoid the expensive calculation of room specific data. This is a micro-optimisation for clients syncing simply to receive to-device information.
This commit is contained in:
		
							parent
							
								
									f36da501be
								
							
						
					
					
						commit
						da05b70af5
					
				
							
								
								
									
										1
									
								
								changelog.d/14908.misc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								changelog.d/14908.misc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
Improve performance of `/sync` in a few situations.
 | 
			
		||||
@ -283,6 +283,9 @@ class FilterCollection:
 | 
			
		||||
            await self._room_filter.filter(events)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def blocks_all_rooms(self) -> bool:
 | 
			
		||||
        return self._room_filter.filters_all_rooms()
 | 
			
		||||
 | 
			
		||||
    def blocks_all_presence(self) -> bool:
 | 
			
		||||
        return (
 | 
			
		||||
            self._presence_filter.filters_all_types()
 | 
			
		||||
 | 
			
		||||
@ -1448,22 +1448,47 @@ class SyncHandler:
 | 
			
		||||
            sync_result_builder
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # Presence data is included if the server has it enabled and not filtered out.
 | 
			
		||||
        include_presence_data = bool(
 | 
			
		||||
            self.hs_config.server.use_presence
 | 
			
		||||
            and not sync_config.filter_collection.blocks_all_presence()
 | 
			
		||||
        )
 | 
			
		||||
        # Device list updates are sent if a since token is provided.
 | 
			
		||||
        include_device_list_updates = bool(since_token and since_token.device_list_key)
 | 
			
		||||
 | 
			
		||||
        # If we do not care about the rooms or things which depend on the room
 | 
			
		||||
        # data (namely presence and device list updates), then we can skip
 | 
			
		||||
        # this process completely.
 | 
			
		||||
        device_lists = DeviceListUpdates()
 | 
			
		||||
        if (
 | 
			
		||||
            not sync_result_builder.sync_config.filter_collection.blocks_all_rooms()
 | 
			
		||||
            or include_presence_data
 | 
			
		||||
            or include_device_list_updates
 | 
			
		||||
        ):
 | 
			
		||||
            logger.debug("Fetching room data")
 | 
			
		||||
 | 
			
		||||
            # Note that _generate_sync_entry_for_rooms sets sync_result_builder.joined, which
 | 
			
		||||
            # is used in calculate_user_changes below.
 | 
			
		||||
            (
 | 
			
		||||
                newly_joined_rooms,
 | 
			
		||||
            newly_joined_or_invited_or_knocked_users,
 | 
			
		||||
                newly_left_rooms,
 | 
			
		||||
            newly_left_users,
 | 
			
		||||
            ) = await self._generate_sync_entry_for_rooms(
 | 
			
		||||
                sync_result_builder, account_data_by_room
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        # Presence data is included if the server has it enabled and not filtered out.
 | 
			
		||||
        include_presence_data = (
 | 
			
		||||
            self.hs_config.server.use_presence
 | 
			
		||||
            and not sync_config.filter_collection.blocks_all_presence()
 | 
			
		||||
        )
 | 
			
		||||
            # Work out which users have joined or left rooms we're in. We use this
 | 
			
		||||
            # to build the presence and device_list parts of the sync response in
 | 
			
		||||
            # `_generate_sync_entry_for_presence` and
 | 
			
		||||
            # `_generate_sync_entry_for_device_list` respectively.
 | 
			
		||||
            if include_presence_data or include_device_list_updates:
 | 
			
		||||
                # This uses the sync_result_builder.joined which is set in
 | 
			
		||||
                # `_generate_sync_entry_for_rooms`, if that didn't find any joined
 | 
			
		||||
                # rooms for some reason it is a no-op.
 | 
			
		||||
                (
 | 
			
		||||
                    newly_joined_or_invited_or_knocked_users,
 | 
			
		||||
                    newly_left_users,
 | 
			
		||||
                ) = sync_result_builder.calculate_user_changes()
 | 
			
		||||
 | 
			
		||||
                if include_presence_data:
 | 
			
		||||
                    logger.debug("Fetching presence data")
 | 
			
		||||
                    await self._generate_sync_entry_for_presence(
 | 
			
		||||
@ -1472,9 +1497,7 @@ class SyncHandler:
 | 
			
		||||
                        newly_joined_or_invited_or_knocked_users,
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
        logger.debug("Fetching to-device data")
 | 
			
		||||
        await self._generate_sync_entry_for_to_device(sync_result_builder)
 | 
			
		||||
 | 
			
		||||
                if include_device_list_updates:
 | 
			
		||||
                    device_lists = await self._generate_sync_entry_for_device_list(
 | 
			
		||||
                        sync_result_builder,
 | 
			
		||||
                        newly_joined_rooms=newly_joined_rooms,
 | 
			
		||||
@ -1483,6 +1506,9 @@ class SyncHandler:
 | 
			
		||||
                        newly_left_users=newly_left_users,
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
        logger.debug("Fetching to-device data")
 | 
			
		||||
        await self._generate_sync_entry_for_to_device(sync_result_builder)
 | 
			
		||||
 | 
			
		||||
        logger.debug("Fetching OTK data")
 | 
			
		||||
        device_id = sync_config.device_id
 | 
			
		||||
        one_time_keys_count: JsonDict = {}
 | 
			
		||||
@ -1551,6 +1577,7 @@ class SyncHandler:
 | 
			
		||||
 | 
			
		||||
        user_id = sync_result_builder.sync_config.user.to_string()
 | 
			
		||||
        since_token = sync_result_builder.since_token
 | 
			
		||||
        assert since_token is not None
 | 
			
		||||
 | 
			
		||||
        # Take a copy since these fields will be mutated later.
 | 
			
		||||
        newly_joined_or_invited_or_knocked_users = set(
 | 
			
		||||
@ -1558,7 +1585,6 @@ class SyncHandler:
 | 
			
		||||
        )
 | 
			
		||||
        newly_left_users = set(newly_left_users)
 | 
			
		||||
 | 
			
		||||
        if since_token and since_token.device_list_key:
 | 
			
		||||
        # We want to figure out what user IDs the client should refetch
 | 
			
		||||
        # device keys for, and which users we aren't going to track changes
 | 
			
		||||
        # for anymore.
 | 
			
		||||
@ -1621,11 +1647,9 @@ class SyncHandler:
 | 
			
		||||
        # weren't in the previous sync *or* they left and rejoined.
 | 
			
		||||
        users_that_have_changed.update(newly_joined_or_invited_or_knocked_users)
 | 
			
		||||
 | 
			
		||||
            user_signatures_changed = (
 | 
			
		||||
                await self.store.get_users_whose_signatures_changed(
 | 
			
		||||
        user_signatures_changed = await self.store.get_users_whose_signatures_changed(
 | 
			
		||||
            user_id, since_token.device_list_key
 | 
			
		||||
        )
 | 
			
		||||
            )
 | 
			
		||||
        users_that_have_changed.update(user_signatures_changed)
 | 
			
		||||
 | 
			
		||||
        # Now find users that we no longer track
 | 
			
		||||
@ -1639,11 +1663,7 @@ class SyncHandler:
 | 
			
		||||
            if any(rid in joined_rooms for rid in entries):
 | 
			
		||||
                newly_left_users.discard(user_id)
 | 
			
		||||
 | 
			
		||||
            return DeviceListUpdates(
 | 
			
		||||
                changed=users_that_have_changed, left=newly_left_users
 | 
			
		||||
            )
 | 
			
		||||
        else:
 | 
			
		||||
            return DeviceListUpdates()
 | 
			
		||||
        return DeviceListUpdates(changed=users_that_have_changed, left=newly_left_users)
 | 
			
		||||
 | 
			
		||||
    @trace
 | 
			
		||||
    async def _generate_sync_entry_for_to_device(
 | 
			
		||||
@ -1720,6 +1740,7 @@ class SyncHandler:
 | 
			
		||||
        since_token = sync_result_builder.since_token
 | 
			
		||||
 | 
			
		||||
        if since_token and not sync_result_builder.full_state:
 | 
			
		||||
            # TODO Do not fetch room account data if it will be unused.
 | 
			
		||||
            (
 | 
			
		||||
                global_account_data,
 | 
			
		||||
                account_data_by_room,
 | 
			
		||||
@ -1736,6 +1757,7 @@ class SyncHandler:
 | 
			
		||||
                    sync_config.user
 | 
			
		||||
                )
 | 
			
		||||
        else:
 | 
			
		||||
            # TODO Do not fetch room account data if it will be unused.
 | 
			
		||||
            (
 | 
			
		||||
                global_account_data,
 | 
			
		||||
                account_data_by_room,
 | 
			
		||||
@ -1818,7 +1840,7 @@ class SyncHandler:
 | 
			
		||||
        self,
 | 
			
		||||
        sync_result_builder: "SyncResultBuilder",
 | 
			
		||||
        account_data_by_room: Dict[str, Dict[str, JsonDict]],
 | 
			
		||||
    ) -> Tuple[AbstractSet[str], AbstractSet[str], AbstractSet[str], AbstractSet[str]]:
 | 
			
		||||
    ) -> Tuple[AbstractSet[str], AbstractSet[str]]:
 | 
			
		||||
        """Generates the rooms portion of the sync response. Populates the
 | 
			
		||||
        `sync_result_builder` with the result.
 | 
			
		||||
 | 
			
		||||
@ -1831,24 +1853,22 @@ class SyncHandler:
 | 
			
		||||
            account_data_by_room: Dictionary of per room account data
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            Returns a 4-tuple describing rooms the user has joined or left, and users who've
 | 
			
		||||
            joined or left rooms any rooms the user is in. This gets used later in
 | 
			
		||||
            `_generate_sync_entry_for_device_list`.
 | 
			
		||||
            Returns a 2-tuple describing rooms the user has joined or left.
 | 
			
		||||
 | 
			
		||||
            Its entries are:
 | 
			
		||||
            - newly_joined_rooms
 | 
			
		||||
            - newly_joined_or_invited_or_knocked_users
 | 
			
		||||
            - newly_left_rooms
 | 
			
		||||
            - newly_left_users
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        since_token = sync_result_builder.since_token
 | 
			
		||||
        user_id = sync_result_builder.sync_config.user.to_string()
 | 
			
		||||
 | 
			
		||||
        # 1. Start by fetching all ephemeral events in rooms we've joined (if required).
 | 
			
		||||
        if (
 | 
			
		||||
            sync_result_builder.sync_config.filter_collection.blocks_all_room_ephemeral()
 | 
			
		||||
        ):
 | 
			
		||||
        block_all_room_ephemeral = (
 | 
			
		||||
            sync_result_builder.sync_config.filter_collection.blocks_all_rooms()
 | 
			
		||||
            or sync_result_builder.sync_config.filter_collection.blocks_all_room_ephemeral()
 | 
			
		||||
        )
 | 
			
		||||
        if block_all_room_ephemeral:
 | 
			
		||||
            ephemeral_by_room: Dict[str, List[JsonDict]] = {}
 | 
			
		||||
        else:
 | 
			
		||||
            now_token, ephemeral_by_room = await self.ephemeral_by_room(
 | 
			
		||||
@ -1870,7 +1890,7 @@ class SyncHandler:
 | 
			
		||||
                    )
 | 
			
		||||
                    if not tags_by_room:
 | 
			
		||||
                        logger.debug("no-oping sync")
 | 
			
		||||
                        return set(), set(), set(), set()
 | 
			
		||||
                        return set(), set()
 | 
			
		||||
 | 
			
		||||
        # 3. Work out which rooms need reporting in the sync response.
 | 
			
		||||
        ignored_users = await self.store.ignored_users(user_id)
 | 
			
		||||
@ -1899,6 +1919,7 @@ class SyncHandler:
 | 
			
		||||
        # joined or archived).
 | 
			
		||||
        async def handle_room_entries(room_entry: "RoomSyncResultBuilder") -> None:
 | 
			
		||||
            logger.debug("Generating room entry for %s", room_entry.room_id)
 | 
			
		||||
            # Note that this mutates sync_result_builder.{joined,archived}.
 | 
			
		||||
            await self._generate_room_entry(
 | 
			
		||||
                sync_result_builder,
 | 
			
		||||
                room_entry,
 | 
			
		||||
@ -1915,20 +1936,7 @@ class SyncHandler:
 | 
			
		||||
        sync_result_builder.invited.extend(invited)
 | 
			
		||||
        sync_result_builder.knocked.extend(knocked)
 | 
			
		||||
 | 
			
		||||
        # 5. Work out which users have joined or left rooms we're in. We use this
 | 
			
		||||
        # to build the device_list part of the sync response in
 | 
			
		||||
        # `_generate_sync_entry_for_device_list`.
 | 
			
		||||
        (
 | 
			
		||||
            newly_joined_or_invited_or_knocked_users,
 | 
			
		||||
            newly_left_users,
 | 
			
		||||
        ) = sync_result_builder.calculate_user_changes()
 | 
			
		||||
 | 
			
		||||
        return (
 | 
			
		||||
            set(newly_joined_rooms),
 | 
			
		||||
            newly_joined_or_invited_or_knocked_users,
 | 
			
		||||
            set(newly_left_rooms),
 | 
			
		||||
            newly_left_users,
 | 
			
		||||
        )
 | 
			
		||||
        return set(newly_joined_rooms), set(newly_left_rooms)
 | 
			
		||||
 | 
			
		||||
    async def _have_rooms_changed(
 | 
			
		||||
        self, sync_result_builder: "SyncResultBuilder"
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user