atagen

matrix-rust-sdk

public
Star0
Watch0
ssh://brewery@pls.lobotomise.me:33/atagen/matrix-rust-sdk.git
benchmarks/benches/crypto_bench.rsRust324 lines10.7 KB
1
use std::{ops::Deref, sync::Arc};
2
3
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
4
use matrix_sdk_crypto::{EncryptionSettings, OlmMachine};
5
use matrix_sdk_sqlite::SqliteCryptoStore;
6
use matrix_sdk_test::ruma_response_from_json;
7
use ruma::{
8
    DeviceId, OwnedUserId, TransactionId, UserId,
9
    api::client::{
10
        keys::{claim_keys, get_keys},
11
        to_device::send_event_to_device::v3::Response as ToDeviceResponse,
12
    },
13
    device_id, room_id, user_id,
14
};
15
use serde_json::Value;
16
use tokio::runtime::Builder;
17
18
fn alice_id() -> &'static UserId {
19
    user_id!("@alice:example.org")
20
}
21
22
fn alice_device_id() -> &'static DeviceId {
23
    device_id!("JLAFKJWSCS")
24
}
25
26
fn keys_query_response() -> get_keys::v3::Response {
27
    let data = include_bytes!("crypto_bench/keys_query.json");
28
    let data: Value = serde_json::from_slice(data).unwrap();
29
    ruma_response_from_json(&data)
30
}
31
32
fn keys_claim_response() -> claim_keys::v3::Response {
33
    let data = include_bytes!("crypto_bench/keys_claim.json");
34
    let data: Value = serde_json::from_slice(data).unwrap();
35
    ruma_response_from_json(&data)
36
}
37
38
fn huge_keys_query_response() -> get_keys::v3::Response {
39
    let data = include_bytes!("crypto_bench/keys_query_2000_members.json");
40
    let data: Value = serde_json::from_slice(data).unwrap();
41
    ruma_response_from_json(&data)
42
}
43
44
pub fn keys_query(c: &mut Criterion) {
45
    let runtime = Builder::new_multi_thread().build().expect("Can't create runtime");
46
    let machine = runtime.block_on(OlmMachine::new(alice_id(), alice_device_id()));
47
    let response = keys_query_response();
48
    let txn_id = TransactionId::new();
49
50
    let count = response.device_keys.values().fold(0, |acc, d| acc + d.len())
51
        + response.master_keys.len()
52
        + response.self_signing_keys.len()
53
        + response.user_signing_keys.len();
54
55
    let mut group = c.benchmark_group("Keys querying");
56
    group.throughput(Throughput::Elements(count as u64));
57
58
    let name = format!("{count} device and cross signing keys");
59
60
    // Benchmark memory store.
61
62
    group.bench_with_input(
63
        BenchmarkId::new("Device keys query [memory]", &name),
64
        &response,
65
        |b, response| {
66
            b.to_async(&runtime)
67
                .iter(|| async { machine.mark_request_as_sent(&txn_id, response).await.unwrap() })
68
        },
69
    );
70
71
    // Benchmark sqlite store.
72
73
    let dir = tempfile::tempdir().unwrap();
74
    let store = Arc::new(runtime.block_on(SqliteCryptoStore::open(dir.path(), None)).unwrap());
75
    let machine = runtime
76
        .block_on(OlmMachine::with_store(alice_id(), alice_device_id(), store, None))
77
        .unwrap();
78
79
    group.bench_with_input(
80
        BenchmarkId::new("Device keys query [SQLite]", &name),
81
        &response,
82
        |b, response| {
83
            b.to_async(&runtime)
84
                .iter(|| async { machine.mark_request_as_sent(&txn_id, response).await.unwrap() })
85
        },
86
    );
87
88
    {
89
        let _guard = runtime.enter();
90
        drop(machine);
91
    }
92
93
    group.finish()
94
}
95
96
/// This test panics on the CI, not sure why so we're disabling it for now.
97
#[cfg(not(feature = "codspeed"))]
98
pub fn keys_claiming(c: &mut Criterion) {
99
    let runtime = Builder::new_multi_thread().build().expect("Can't create runtime");
100
101
    let keys_query_response = keys_query_response();
102
    let txn_id = TransactionId::new();
103
104
    let response = keys_claim_response();
105
106
    let count = response.one_time_keys.values().fold(0, |acc, d| acc + d.len());
107
108
    let mut group = c.benchmark_group("Olm session creation");
109
    group.throughput(Throughput::Elements(count as u64));
110
111
    let name = format!("{count} one-time keys");
112
113
    group.bench_with_input(
114
        BenchmarkId::new("One-time keys claiming [memory]", &name),
115
        &response,
116
        |b, response| {
117
            b.iter_batched(
118
                || {
119
                    let machine = runtime.block_on(OlmMachine::new(alice_id(), alice_device_id()));
120
                    runtime
121
                        .block_on(machine.mark_request_as_sent(&txn_id, &keys_query_response))
122
                        .unwrap();
123
                    (machine, &runtime, &txn_id)
124
                },
125
                move |(machine, runtime, txn_id)| {
126
                    runtime.block_on(async {
127
                        machine.mark_request_as_sent(txn_id, response).await.unwrap();
128
                        drop(machine);
129
                    })
130
                },
131
                criterion::BatchSize::SmallInput,
132
            )
133
        },
134
    );
135
136
    group.bench_with_input(
137
        BenchmarkId::new("One-time keys claiming [SQLite]", &name),
138
        &response,
139
        |b, response| {
140
            b.iter_batched(
141
                || {
142
                    let dir = tempfile::tempdir().unwrap();
143
                    let store = Arc::new(
144
                        runtime.block_on(SqliteCryptoStore::open(dir.path(), None)).unwrap(),
145
                    );
146
147
                    let machine = runtime
148
                        .block_on(OlmMachine::with_store(
149
                            alice_id(),
150
                            alice_device_id(),
151
                            store,
152
                            None,
153
                        ))
154
                        .unwrap();
155
                    runtime
156
                        .block_on(machine.mark_request_as_sent(&txn_id, &keys_query_response))
157
                        .unwrap();
158
                    (machine, &runtime, &txn_id)
159
                },
160
                move |(machine, runtime, txn_id)| {
161
                    runtime.block_on(async {
162
                        machine.mark_request_as_sent(txn_id, response).await.unwrap();
163
                    });
164
165
                    let _ = runtime.enter();
166
                    drop(machine);
167
                },
168
                criterion::BatchSize::SmallInput,
169
            )
170
        },
171
    );
172
173
    group.finish()
174
}
175
176
pub fn room_key_sharing(c: &mut Criterion) {
177
    let runtime = Builder::new_multi_thread().build().expect("Can't create runtime");
178
179
    let keys_query_response = keys_query_response();
180
    let txn_id = TransactionId::new();
181
    let response = keys_claim_response();
182
    let room_id = room_id!("!test:localhost");
183
184
    let to_device_response = ToDeviceResponse::new();
185
    let users: Vec<OwnedUserId> = keys_query_response.device_keys.keys().cloned().collect();
186
187
    let count = response.one_time_keys.values().fold(0, |acc, d| acc + d.len());
188
189
    let machine = runtime.block_on(OlmMachine::new(alice_id(), alice_device_id()));
190
    runtime.block_on(machine.mark_request_as_sent(&txn_id, &keys_query_response)).unwrap();
191
    runtime.block_on(machine.mark_request_as_sent(&txn_id, &response)).unwrap();
192
193
    let mut group = c.benchmark_group("Room key sharing");
194
    group.throughput(Throughput::Elements(count as u64));
195
    let name = format!("{count} devices");
196
197
    // Benchmark memory store.
198
199
    group.bench_function(BenchmarkId::new("Room key sharing [memory]", &name), |b| {
200
        b.to_async(&runtime).iter(|| async {
201
            let requests = machine
202
                .share_room_key(
203
                    room_id,
204
                    users.iter().map(Deref::deref),
205
                    EncryptionSettings::default(),
206
                )
207
                .await
208
                .unwrap();
209
210
            assert!(!requests.is_empty());
211
212
            for request in requests {
213
                machine.mark_request_as_sent(&request.txn_id, &to_device_response).await.unwrap();
214
            }
215
216
            machine.discard_room_key(room_id).await.unwrap();
217
        })
218
    });
219
220
    // Benchmark sqlite store.
221
222
    let dir = tempfile::tempdir().unwrap();
223
    let store = Arc::new(runtime.block_on(SqliteCryptoStore::open(dir.path(), None)).unwrap());
224
225
    let machine = runtime
226
        .block_on(OlmMachine::with_store(alice_id(), alice_device_id(), store, None))
227
        .unwrap();
228
    runtime.block_on(machine.mark_request_as_sent(&txn_id, &keys_query_response)).unwrap();
229
    runtime.block_on(machine.mark_request_as_sent(&txn_id, &response)).unwrap();
230
231
    group.bench_function(BenchmarkId::new("Room key sharing [SQLite]", &name), |b| {
232
        b.to_async(&runtime).iter(|| async {
233
            let requests = machine
234
                .share_room_key(
235
                    room_id,
236
                    users.iter().map(Deref::deref),
237
                    EncryptionSettings::default(),
238
                )
239
                .await
240
                .unwrap();
241
242
            assert!(!requests.is_empty());
243
244
            for request in requests {
245
                machine.mark_request_as_sent(&request.txn_id, &to_device_response).await.unwrap();
246
            }
247
248
            machine.discard_room_key(room_id).await.unwrap();
249
        })
250
    });
251
252
    {
253
        let _guard = runtime.enter();
254
        drop(machine);
255
    }
256
257
    group.finish()
258
}
259
260
pub fn devices_missing_sessions_collecting(c: &mut Criterion) {
261
    let runtime = Builder::new_multi_thread().build().expect("Can't create runtime");
262
263
    let machine = runtime.block_on(OlmMachine::new(alice_id(), alice_device_id()));
264
    let response = huge_keys_query_response();
265
    let txn_id = TransactionId::new();
266
    let users: Vec<OwnedUserId> = response.device_keys.keys().cloned().collect();
267
268
    let count = response.device_keys.values().fold(0, |acc, d| acc + d.len());
269
270
    let mut group = c.benchmark_group("Devices missing sessions collecting");
271
    group.throughput(Throughput::Elements(count as u64));
272
273
    let name = format!("{count} devices");
274
275
    runtime.block_on(machine.mark_request_as_sent(&txn_id, &response)).unwrap();
276
277
    // Benchmark memory store.
278
279
    group.bench_function(BenchmarkId::new("Devices collecting [memory]", &name), |b| {
280
        b.to_async(&runtime).iter_with_large_drop(|| async {
281
            machine.get_missing_sessions(users.iter().map(Deref::deref)).await.unwrap()
282
        })
283
    });
284
285
    // Benchmark sqlite store.
286
287
    let dir = tempfile::tempdir().unwrap();
288
    let store = Arc::new(runtime.block_on(SqliteCryptoStore::open(dir.path(), None)).unwrap());
289
290
    let machine = runtime
291
        .block_on(OlmMachine::with_store(alice_id(), alice_device_id(), store, None))
292
        .unwrap();
293
294
    runtime.block_on(machine.mark_request_as_sent(&txn_id, &response)).unwrap();
295
296
    group.bench_function(BenchmarkId::new("Devices collecting [SQLite]", &name), |b| {
297
        b.to_async(&runtime).iter(|| async {
298
            machine.get_missing_sessions(users.iter().map(Deref::deref)).await.unwrap()
299
        })
300
    });
301
302
    {
303
        let _guard = runtime.enter();
304
        drop(machine);
305
    }
306
307
    group.finish()
308
}
309
310
#[cfg(not(feature = "codspeed"))]
311
criterion_group! {
312
    name = benches;
313
    config = Criterion::default();
314
    targets = keys_query, keys_claiming, room_key_sharing, devices_missing_sessions_collecting,
315
}
316
317
#[cfg(feature = "codspeed")]
318
criterion_group! {
319
    name = benches;
320
    config = Criterion::default();
321
    targets = keys_query, room_key_sharing, devices_missing_sessions_collecting,
322
}
323
324
criterion_main!(benches);