-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Re-use work of getting state for a given state_group
(_get_state_groups_from_groups
)
#15617
Re-use work of getting state for a given state_group
(_get_state_groups_from_groups
)
#15617
Conversation
results[group] = partial_state_map_for_state_group | ||
|
||
state_groups_we_have_already_fetched.add(group) | ||
|
||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To not complicate the diff, I've held off on applying the same treatment to SQLite.
We can iterate on this in another PR or just opt for people to use Postgres in order to see performance
…rom-previous-group
results[group] = partial_state_map_for_state_group | ||
|
||
state_groups_we_have_already_fetched.add(group) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After
[...]
In the sample request above, simulating how the app would make the queries with the changes in this PR, we don't actually see that much benefit because it turns out that there isn't much
state_group
sharing amongst events. That 14s SQL query is just fetching the state at each of theprev_events
of one event and only one seems to sharestate_groups
.[...]
Initially, I thought the lack of sharing was quite strange but this is because of the state_group snapshotting feature where if an event requires more than 100 hops on
state_event_edges
, then a Synaspe will create a newstate_group
with a snapshot of all of that state. It seems like this isn't done very efficiently though. Relevant docs.And it turns out the event is an
org.matrix.dummy_event
which Synapse automatically puts in the DAG to resolve outstanding forward extremities and these events aren't even shown to clients so we don't even need to waste time waiting for them to backfill. Tracked by #15632Generally, I think this PR could bring great gains in conjunction to running some sort of state compressor over the database to get a lot more sharing. In addition to trying to fix the online state_group snapshotting logic to be smarter. I don't know how the existing state_compressors work but I imagine we could create snapshots and bucket for years -> months -> weeks -> days -> hours -> individual events and create new
state_group
chains which utilize these from biggest to smallest to get maximal sharing.-- "After" section of the PR description
This PR hasn't made as big of an impact as I thought it would for that type of request. Are we still interested in a change like this? It may work well for sequential events that we backfill.
It seems like our state_group
sharing is realllly sub-par and the way that state_groups
can only have a max of 100 hops puts an upper limit on how much gain this PR can give. I didn't anticipate that's how state_groups
worked and thought it was one state_group
per-state-change which it is until it starts doing snapshots.
Maybe it's more interesting to improve our state_group
logic to be much smarter first and we could re-visit something like this. Or look into the state compressor stuff to optimize our backlog which would help for the Matrix Public Archive. I'm not sure if the current state compressors optimize for disk space or sharing or how inter-related those two goals are.
state_group
state_group
(_get_state_groups_from_groups
)
It sounds like this didn't make much of an improvement and significantly complicates the code. I'm going to close this due to that, but I did grab the nice improvements to the comments and move them to #16383. |
Re-use work of getting state for a given
state_group
. This is useful when we_compute_event_context_with_maybe_missing_prevs(...)
->_get_state_groups_from_groups(...)
Part of making
/messages
faster: #13356Background (explaining the situation before this PR)
When we have to
_compute_event_context_with_maybe_missing_prevs
,_get_state_groups_from_groups
currently takes up most of the time. It makes the following recursive query for each state group given which goes up the entire state_group chain and returns the complete distinct state which means thousands of membership events at the very least. For example, with a random/messages
request in the Matrix HQ room we did 10x of these queries which each took 0.5-2 seconds and return roughly 88k events every time totaling 14s.https://explain.depesz.com/s/OuOe
https://explain.dalibo.com/plan/ef6bc290f2dced17
EXPLAIN ANAYLZE
query outputFull Jaeger trace JSON
Before
Say we have
state_groups
1-10 wherestate_group
1
would be them.room.create
, and then onwards, etc.Currently, when you ask for the state at
state_groups = [5, 8]
, we will fetch state from5 -> 1
and8 -> 1
which is pretty wasteful because we're mostly fetching the same thing again and time consuming (imagine this with Matrix HQ which has chains of 88k events).After
Now instead when you ask for the state at
state_groups = [5, 8]
, we fetch5 -> 1
as normal, but then only fetch8 -> 5
and layer it on top of the work we did for the state atstate_group = 5
.In terms of query performance, our first query will take the same amount of time as before but any subsequent state_groups that are shared will take significantly less time.
In the sample request above, simulating how the app would make the queries with the changes in this PR, we don't actually see that much benefit because it turns out that there isn't much
state_group
sharing amongst events. That 14s SQL query is just fetching the state at each of theprev_events
of one event and only one seems to sharestate_groups
.state_group
chains not actually shared that much in that 14s database query 😬Initially, I thought the lack of sharing was quite strange but this is because of the state_group snapshotting feature where if an event requires more than 100 hops on
state_event_edges
, then a Synaspe will create a newstate_group
with a snapshot of all of that state. It seems like this isn't done very efficiently though. Relevant docs.And it turns out the event is an
org.matrix.dummy_event
which Synapse automatically puts in the DAG to resolve outstanding forward extremities and these events aren't even shown to clients so we don't even need to waste time waiting for them to backfill. Tracked by #15632Generally, I think this PR could bring great gains in conjunction to running some sort of state compressor over the database to get a lot more sharing. In addition to trying to fix the online state_group snapshotting logic to be smarter. I don't know how the existing state_compressors work but I imagine we could create snapshots and bucket for years -> months -> weeks -> days -> hours -> individual events and create new
state_group
chains which utilize these from biggest to smallest to get maximal sharing.Dev notes
Pull Request Checklist
EventStore
toEventWorkerStore
.".code blocks
.Pull request includes a sign off(run the linters)