From a9c146ac53a40d191c0a2b3b1b8f6ceaea0eee79 Mon Sep 17 00:00:00 2001
From: Richard van der Hoff <richard@matrix.org>
Date: Wed, 15 Dec 2021 13:08:24 +0000
Subject: [PATCH 1/2] Disable aggregation bundling on `/sync` responses

A partial revert of #11478. This turns out to have had a significant CPU impact
on initial-sync handling. For now, let's disable it, until we find a more
efficient way of achieving this.
---
 changelog.d/11583.bugfix    | 1 +
 synapse/rest/client/sync.py | 8 +++++++-
 2 files changed, 8 insertions(+), 1 deletion(-)
 create mode 100644 changelog.d/11583.bugfix

diff --git a/changelog.d/11583.bugfix b/changelog.d/11583.bugfix
new file mode 100644
index 000000000000..d2ed113e2128
--- /dev/null
+++ b/changelog.d/11583.bugfix
@@ -0,0 +1 @@
+Fix a performance regression in `/sync` handling, introduced in 1.49.0.
diff --git a/synapse/rest/client/sync.py b/synapse/rest/client/sync.py
index 88e4f5e0630f..e556ff93e670 100644
--- a/synapse/rest/client/sync.py
+++ b/synapse/rest/client/sync.py
@@ -522,7 +522,13 @@ def serialize(events: Iterable[EventBase]) -> Awaitable[List[JsonDict]]:
                 time_now=time_now,
                 # Don't bother to bundle aggregations if the timeline is unlimited,
                 # as clients will have all the necessary information.
-                bundle_aggregations=room.timeline.limited,
+                # bundle_aggregations=room.timeline.limited,
+                #
+                # richvdh 2021-12-15: disable this temporarily as it has too high an
+                # overhead for initialsyncs. We need to figure out a way that the
+                # bundling can be done *before* the events are stored in the
+                # SyncResponseCache so that this part can be synchronous.
+                bundle_aggregations=False,
                 token_id=token_id,
                 event_format=event_formatter,
                 only_event_fields=only_fields,

From eca24d7d2880f7eb7350d919d93c839c82da9a92 Mon Sep 17 00:00:00 2001
From: Patrick Cloke <patrickc@matrix.org>
Date: Wed, 15 Dec 2021 11:18:23 -0500
Subject: [PATCH 2/2] Fix tests.

---
 synapse/rest/client/sync.py         |  2 ++
 tests/rest/client/test_relations.py | 10 +++++-----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/synapse/rest/client/sync.py b/synapse/rest/client/sync.py
index e556ff93e670..7f5846d38934 100644
--- a/synapse/rest/client/sync.py
+++ b/synapse/rest/client/sync.py
@@ -528,6 +528,8 @@ def serialize(events: Iterable[EventBase]) -> Awaitable[List[JsonDict]]:
                 # overhead for initialsyncs. We need to figure out a way that the
                 # bundling can be done *before* the events are stored in the
                 # SyncResponseCache so that this part can be synchronous.
+                #
+                # Ensure to re-enable the test at tests/rest/client/test_relations.py::RelationsTestCase.test_bundled_aggregations.
                 bundle_aggregations=False,
                 token_id=token_id,
                 event_format=event_formatter,
diff --git a/tests/rest/client/test_relations.py b/tests/rest/client/test_relations.py
index 397c12c2a6c5..1b58b73136c5 100644
--- a/tests/rest/client/test_relations.py
+++ b/tests/rest/client/test_relations.py
@@ -574,11 +574,11 @@ def _find_and_assert_event(events):
         assert_bundle(channel.json_body["event"]["unsigned"].get("m.relations"))
 
         # Request sync.
-        channel = self.make_request("GET", "/sync", access_token=self.user_token)
-        self.assertEquals(200, channel.code, channel.json_body)
-        room_timeline = channel.json_body["rooms"]["join"][self.room]["timeline"]
-        self.assertTrue(room_timeline["limited"])
-        _find_and_assert_event(room_timeline["events"])
+        # channel = self.make_request("GET", "/sync", access_token=self.user_token)
+        # self.assertEquals(200, channel.code, channel.json_body)
+        # room_timeline = channel.json_body["rooms"]["join"][self.room]["timeline"]
+        # self.assertTrue(room_timeline["limited"])
+        # _find_and_assert_event(room_timeline["events"])
 
         # Note that /relations is tested separately in test_aggregation_get_event_for_thread
         # since it needs different data configured.