atagen

matrix-rust-sdk

public
Star0
Watch0
ssh://brewery@pls.lobotomise.me:33/atagen/matrix-rust-sdk.git
benchmarks/benches/timeline.rsRust123 lines4.6 KB
1
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
2
use matrix_sdk::test_utils::mocks::MatrixMockServer;
3
use matrix_sdk_test::{JoinedRoomBuilder, event_factory::EventFactory};
4
use matrix_sdk_ui::timeline::{TimelineBuilder, TimelineReadReceiptTracking};
5
use ruma::{
6
    OwnedEventId, events::room::message::RoomMessageEventContentWithoutRelation, owned_room_id,
7
    owned_user_id,
8
};
9
use tokio::runtime::Builder;
10
11
/// Benchmark the time it takes to create a timeline (with read receipt
12
/// support), when there are many initial events at rest in the event cache.
13
///
14
/// `NUM_EVENTS` is the number of events that will be stored initially in the
15
/// event cache. It will be a mix of messages, reactions, edits and redactions,
16
/// so there are some aggregations to take into account by the timeline as well.
17
pub fn create_timeline_with_initial_events(c: &mut Criterion) {
18
    const NUM_EVENTS: usize = 10000;
19
20
    let runtime = Builder::new_multi_thread().enable_all().build().expect("Can't create runtime");
21
    let room_id = owned_room_id!("!fortesfortunajuvat:example.com");
22
23
    let sender_id = owned_user_id!("@sender:example.com");
24
    let other_sender_id = owned_user_id!("@other_sender:example.com");
25
    let another_sender_id = owned_user_id!("@another_sender:example.com");
26
27
    let f = EventFactory::new().room(&room_id);
28
29
    let mut events = Vec::new();
30
    for i in 0..NUM_EVENTS {
31
        let sender = match i % 3 {
32
            0 => &sender_id,
33
            1 => &other_sender_id,
34
            2 => &another_sender_id,
35
            _ => unreachable!("math genius over here"),
36
        };
37
38
        let j = i % 10;
39
        if j < 6 {
40
            // Messages.
41
            events.push(f.text_msg(format!("Message {i}")).sender(sender).into_raw_sync());
42
        } else if j < 8 {
43
            // Reactions.
44
            let prev_event_id = events[i - 2]
45
                .get_field::<OwnedEventId>("event_id")
46
                .expect("invalid event ID")
47
                .expect("missing event ID");
48
            events.push(f.reaction(&prev_event_id, "👍").sender(sender).into_raw_sync());
49
        } else if j == 8 {
50
            // Edit.
51
            // Note: (i-3)%3 is the same as i%3 -> same sender!
52
            let prev_event_id = events[i - 3]
53
                .get_field::<OwnedEventId>("event_id")
54
                .expect("invalid event ID")
55
                .expect("missing event ID");
56
            events.push(
57
                f.text_msg(format!("* Message {}v2", i - 3))
58
                    .edit(
59
                        &prev_event_id,
60
                        RoomMessageEventContentWithoutRelation::text_plain(format!(
61
                            "Message {}v2",
62
                            i - 3
63
                        )),
64
                    )
65
                    .sender(sender)
66
                    .into_raw_sync(),
67
            );
68
        } else if j == 9 {
69
            // Redaction.
70
            // Note: (i-6)%3 is the same as i%6 -> same sender!
71
            let prev_event_id = events[i - 6]
72
                .get_field::<OwnedEventId>("event_id")
73
                .expect("invalid event ID")
74
                .expect("missing event ID");
75
            events.push(f.redaction(&prev_event_id).sender(sender).into_raw_sync());
76
        }
77
    }
78
79
    let builder = JoinedRoomBuilder::new(&room_id)
80
        .add_state_event(f.room_encryption().sender(&sender_id))
81
        .add_timeline_bulk(events);
82
83
    let room = runtime.block_on(async move {
84
        let server = MatrixMockServer::new().await;
85
        let client = server.client_builder().build().await;
86
87
        client.event_cache().subscribe().unwrap();
88
89
        let room = server.sync_room(&client, builder).await;
90
        drop(server);
91
92
        room
93
    });
94
95
    let mut group = c.benchmark_group("Create a timeline");
96
    group.throughput(Throughput::Elements(NUM_EVENTS as _));
97
    group.sample_size(10);
98
99
    group.bench_function(
100
        BenchmarkId::new("Create a timeline with initial events", format!("{NUM_EVENTS} events")),
101
        |b| {
102
            b.to_async(&runtime).iter(|| async {
103
                let timeline = TimelineBuilder::new(&room)
104
                    .track_read_marker_and_receipts(TimelineReadReceiptTracking::AllEvents)
105
                    .build()
106
                    .await
107
                    .expect("Could not create timeline");
108
109
                let (items, _) = timeline.subscribe().await;
110
                assert_eq!(items.len(), 20);
111
            });
112
        },
113
    );
114
115
    group.finish();
116
}
117
118
criterion_group! {
119
    name = room;
120
    config = Criterion::default();
121
    targets = create_timeline_with_initial_events
122
}
123
criterion_main!(room);