aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Alexander <neilalexander@users.noreply.github.com>2021-01-18 13:21:33 +0000
committerGitHub <noreply@github.com>2021-01-18 13:21:33 +0000
commit244ff0dccb64fbdf29b6cbf8a7e02a81b92c7330 (patch)
tree1ca91fc238e06d4c39a6514dbf01184e7a8f7751
parentdd1e31bee7b96c0e7e1697b21f7f1119b5cc4622 (diff)
Don't create so many state snapshots when updating forward extremities (#1718)
* Light-weight checking of state changes when updating forward extremities * Only do this for non-state events, since state events will always result in state change at extremities
-rw-r--r--roomserver/internal/input/input_latest_events.go40
-rw-r--r--roomserver/state/state.go4
2 files changed, 38 insertions, 6 deletions
diff --git a/roomserver/internal/input/input_latest_events.go b/roomserver/internal/input/input_latest_events.go
index e5ec8c4d..c9264a27 100644
--- a/roomserver/internal/input/input_latest_events.go
+++ b/roomserver/internal/input/input_latest_events.go
@@ -100,7 +100,8 @@ type latestEventsUpdater struct {
// The eventID of the event that was processed before this one.
lastEventIDSent string
// The latest events in the room after processing this event.
- latest []types.StateAtEventAndReference
+ oldLatest []types.StateAtEventAndReference
+ latest []types.StateAtEventAndReference
// The state entries removed from and added to the current state of the
// room as a result of processing this event. They are sorted lists.
removed []types.StateEntry
@@ -123,10 +124,10 @@ func (u *latestEventsUpdater) doUpdateLatestEvents() error {
// state snapshot from somewhere else, e.g. a federated room join,
// then start with an empty set - none of the forward extremities
// that we knew about before matter anymore.
- oldLatest := []types.StateAtEventAndReference{}
+ u.oldLatest = []types.StateAtEventAndReference{}
if !u.rewritesState {
u.oldStateNID = u.updater.CurrentStateSnapshotNID()
- oldLatest = u.updater.LatestEvents()
+ u.oldLatest = u.updater.LatestEvents()
}
// If the event has already been written to the output log then we
@@ -140,7 +141,7 @@ func (u *latestEventsUpdater) doUpdateLatestEvents() error {
// Work out what the latest events are. This will include the new
// event if it is not already referenced.
extremitiesChanged, err := u.calculateLatest(
- oldLatest, u.event,
+ u.oldLatest, u.event,
types.StateAtEventAndReference{
EventReference: u.event.EventReference(),
StateAtEvent: u.stateAtEvent,
@@ -200,6 +201,37 @@ func (u *latestEventsUpdater) latestState() error {
var err error
roomState := state.NewStateResolution(u.api.DB, *u.roomInfo)
+ // Work out if the state at the extremities has actually changed
+ // or not. If they haven't then we won't bother doing all of the
+ // hard work.
+ if u.event.StateKey() == nil {
+ stateChanged := false
+ oldStateNIDs := make([]types.StateSnapshotNID, 0, len(u.oldLatest))
+ newStateNIDs := make([]types.StateSnapshotNID, 0, len(u.latest))
+ for _, old := range u.oldLatest {
+ oldStateNIDs = append(oldStateNIDs, old.BeforeStateSnapshotNID)
+ }
+ for _, new := range u.latest {
+ newStateNIDs = append(newStateNIDs, new.BeforeStateSnapshotNID)
+ }
+ oldStateNIDs = state.UniqueStateSnapshotNIDs(oldStateNIDs)
+ newStateNIDs = state.UniqueStateSnapshotNIDs(newStateNIDs)
+ if len(oldStateNIDs) != len(newStateNIDs) {
+ stateChanged = true
+ } else {
+ for i := range oldStateNIDs {
+ if oldStateNIDs[i] != newStateNIDs[i] {
+ stateChanged = true
+ break
+ }
+ }
+ }
+ if !stateChanged {
+ u.newStateNID = u.oldStateNID
+ return nil
+ }
+ }
+
// Get a list of the current latest events. This may or may not
// include the new event from the input path, depending on whether
// it is a forward extremity or not.
diff --git a/roomserver/state/state.go b/roomserver/state/state.go
index 87715af4..953276b2 100644
--- a/roomserver/state/state.go
+++ b/roomserver/state/state.go
@@ -116,7 +116,7 @@ func (v StateResolution) LoadCombinedStateAfterEvents(
// Deduplicate the IDs before passing them to the database.
// There could be duplicates because the events could be state events where
// the snapshot of the room state before them was the same.
- stateBlockNIDLists, err := v.db.StateBlockNIDs(ctx, uniqueStateSnapshotNIDs(stateNIDs))
+ stateBlockNIDLists, err := v.db.StateBlockNIDs(ctx, UniqueStateSnapshotNIDs(stateNIDs))
if err != nil {
return nil, fmt.Errorf("v.db.StateBlockNIDs: %w", err)
}
@@ -1103,7 +1103,7 @@ func (s stateNIDSorter) Len() int { return len(s) }
func (s stateNIDSorter) Less(i, j int) bool { return s[i] < s[j] }
func (s stateNIDSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-func uniqueStateSnapshotNIDs(nids []types.StateSnapshotNID) []types.StateSnapshotNID {
+func UniqueStateSnapshotNIDs(nids []types.StateSnapshotNID) []types.StateSnapshotNID {
return nids[:util.SortAndUnique(stateNIDSorter(nids))]
}