Skip to content

Commit 51ef2e0

Browse files
committed
refactor(torture): use OrdMap to track the state
1 parent 9adaa35 commit 51ef2e0

File tree

3 files changed

+47
-42
lines changed

3 files changed

+47
-42
lines changed

torture/src/agent.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use anyhow::{anyhow, bail, Result};
22
use futures::SinkExt as _;
33
use nomt::{Blake3Hasher, Nomt};
4-
use rand::Rng;
54
use std::{path::PathBuf, sync::Arc, time::Duration};
65
use tokio::{
76
io::{BufReader, BufWriter},

torture/src/message.rs

+7
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ impl KeyValueChange {
2424
KeyValueChange::Insert(ref key, _) | KeyValueChange::Delete(ref key) => key,
2525
}
2626
}
27+
28+
pub fn value(&self) -> Option<Value> {
29+
match self {
30+
KeyValueChange::Insert(_, val) => Some(val.clone()),
31+
KeyValueChange::Delete(_) => None,
32+
}
33+
}
2734
}
2835

2936
/// The parameters for the [`ToAgent::Init`] message.

torture/src/supervisor/workload.rs

+40-41
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use anyhow::Result;
22
use imbl::OrdMap;
33
use rand::prelude::*;
4-
use std::{collections::BTreeMap, time::Duration};
4+
use std::time::Duration;
55
use tempfile::TempDir;
66
use tokio::time::{error::Elapsed, timeout};
77
use tokio_util::sync::CancellationToken;
@@ -48,10 +48,7 @@ impl Biases {
4848
struct Snapshot {
4949
sync_seqn: u32,
5050
/// The state of the database at this snapshot.
51-
///
52-
/// The key is the key of the key-value pair. Instead of using the 32 bytes of the key, we
53-
/// save the index of the key in the `WorkloadState::mentions` vector.
54-
state: OrdMap<u32, Option<Vec<u8>>>,
51+
state: OrdMap<[u8; 32], Option<Vec<u8>>>,
5552
}
5653

5754
impl Snapshot {
@@ -73,11 +70,6 @@ struct WorkloadState {
7370
random_size: bool,
7471
/// The values that were committed.
7572
committed: Snapshot,
76-
/// All keys that were generated during this run.
77-
///
78-
/// It's extremely unlikely to find any duplicates in there. Each key is very likely to store
79-
/// a value.
80-
mentions: Vec<[u8; 32]>,
8173
}
8274

8375
impl WorkloadState {
@@ -88,7 +80,6 @@ impl WorkloadState {
8880
size,
8981
random_size,
9082
committed: Snapshot::empty(),
91-
mentions: Vec::with_capacity(32 * 1024),
9283
}
9384
}
9485

@@ -112,47 +103,55 @@ impl WorkloadState {
112103
// Commiting requires using only the unique keys. To ensure that we deduplicate the keys
113104
// using a hash set.
114105
let mut used_keys = std::collections::HashSet::with_capacity(num_changes);
115-
for _ in 0..num_changes {
116-
// Generate a key until unique.
117-
let key_index = loop {
118-
let ki = self.gen_key();
119-
if used_keys.insert(ki) {
120-
break ki;
121-
}
122-
};
123-
124-
if self.rng.gen_bool(self.biases.delete) {
125-
snapshot.state.insert(key_index, None);
126-
let key = self.mentions[key_index as usize];
127-
changes.push(KeyValueChange::Delete(key));
128-
} else {
129-
let value = self.gen_value();
130-
snapshot.state.insert(key_index, Some(value.clone()));
131-
let key = self.mentions[key_index as usize];
132-
changes.push(KeyValueChange::Insert(key, value));
133-
};
106+
loop {
107+
let change = self.gen_key_value_change();
108+
if used_keys.contains(change.key()) {
109+
continue;
110+
}
111+
112+
snapshot.state.insert(*change.key(), change.value());
113+
used_keys.insert(*change.key());
114+
changes.push(change);
115+
116+
if used_keys.len() >= num_changes {
117+
break;
118+
}
134119
}
135120

136121
changes.sort_by(|a, b| a.key().cmp(&b.key()));
137122

138123
(snapshot, changes)
139124
}
140125

141-
/// Returns a key that was generated before or a new key. The returned value is an index in the
142-
/// `mentions` vector.
143-
fn gen_key(&mut self) -> u32 {
126+
/// Returns a KeyValueChange with a new key, a deleted or a modified one.
127+
fn gen_key_value_change(&mut self) -> KeyValueChange {
144128
// TODO: sophisticated key generation.
145129
//
146130
// - Pick a key that was already generated before, but generate a key that shares some bits.
147-
if self.mentions.is_empty() || self.rng.gen_bool(self.biases.new_key) {
148-
let mut key = [0; 32];
131+
let mut key = [0; 32];
132+
if !self.committed.state.is_empty() && self.rng.gen_bool(self.biases.delete) {
133+
loop {
134+
self.rng.fill_bytes(&mut key);
135+
if let Some((next_key, Some(_))) = self.committed.state.get_next(&key) {
136+
return KeyValueChange::Delete(*next_key);
137+
}
138+
}
139+
}
140+
141+
if self.committed.state.is_empty() || self.rng.gen_bool(self.biases.new_key) {
142+
loop {
143+
self.rng.fill_bytes(&mut key);
144+
if !self.committed.state.contains_key(&key) {
145+
return KeyValueChange::Insert(key, self.gen_value());
146+
}
147+
}
148+
}
149+
150+
loop {
149151
self.rng.fill_bytes(&mut key);
150-
let ix = self.mentions.len() as u32;
151-
self.mentions.push(key.clone());
152-
ix
153-
} else {
154-
let ix = self.rng.gen_range(0..self.mentions.len());
155-
ix as u32
152+
if let Some((next_key, _)) = self.committed.state.get_next(&key) {
153+
return KeyValueChange::Insert(*next_key, self.gen_value());
154+
}
156155
}
157156
}
158157

0 commit comments

Comments
 (0)