diff --git a/roomserver/api/perform.go b/roomserver/api/perform.go index 2818efaa3..22346df80 100644 --- a/roomserver/api/perform.go +++ b/roomserver/api/perform.go @@ -93,11 +93,19 @@ type PerformBackfillRequest struct { // PrevEventIDs returns the prev_event IDs of all backwards extremities, de-duplicated in a lexicographically sorted order. func (r *PerformBackfillRequest) PrevEventIDs() []string { - var prevEventIDs []string + // Collect 1k eventIDs, if possible, they may be cleared out below + prevEventIDs := make([]string, 0, len(r.BackwardsExtremities)*3) for _, pes := range r.BackwardsExtremities { prevEventIDs = append(prevEventIDs, pes...) + if len(prevEventIDs) > 1000 { + break + } } prevEventIDs = util.UniqueStrings(prevEventIDs) + // If we still have > 100 eventIDs, only return the first 100 + if len(prevEventIDs) > 100 { + return prevEventIDs[:100] + } return prevEventIDs } diff --git a/roomserver/api/perform_test.go b/roomserver/api/perform_test.go new file mode 100644 index 000000000..4a6e9238f --- /dev/null +++ b/roomserver/api/perform_test.go @@ -0,0 +1,53 @@ +package api + +import ( + "fmt" + "math/rand" + "testing" +) + +func BenchmarkPrevEventIDs(b *testing.B) { + for _, x := range []int64{1, 2, 4, 10, 50, 100, 300, 500, 800, 1000, 2000, 3000, 5000, 10000} { + benchPrevEventIDs(b, int(x)) + } +} + +func benchPrevEventIDs(b *testing.B, count int) { + b.Run(fmt.Sprintf("Benchmark%d", count), func(b *testing.B) { + bwExtrems := generateBackwardsExtremities(b, count) + backfiller := PerformBackfillRequest{ + BackwardsExtremities: bwExtrems, + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + prevIDs := backfiller.PrevEventIDs() + _ = prevIDs + } + }) +} + +func generateBackwardsExtremities(b *testing.B, count int) map[string][]string { + b.Helper() + result := make(map[string][]string, count) + for i := 0; i < count; i++ { + eventID := randomEventId(int64(i), 10) + result[eventID] = []string{ + randomEventId(int64(i+1), 10), + randomEventId(int64(i+2), 10), + randomEventId(int64(i+3), 10), + } + } + return result +} + +const alphanumerics = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + +// RandomString generates a pseudo-random string of length n. +func randomEventId(src int64, n int) string { + randSrc := rand.NewSource(src) + b := make([]byte, n) + for i := range b { + b[i] = alphanumerics[randSrc.Int63()%int64(len(alphanumerics))] + } + return string(b) +}