test: ptth_kv is slower with async, but still fast enough

main
_ 2021-01-03 20:05:05 +00:00
parent 27f31d0ef4
commit eb927ef80d
3 changed files with 35 additions and 23 deletions

1
Cargo.lock generated
View File

@ -1662,6 +1662,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"base64 0.13.0", "base64 0.13.0",
"thiserror", "thiserror",
"tokio",
] ]
[[package]] [[package]]

View File

@ -7,3 +7,4 @@ edition = "2018"
[dependencies] [dependencies]
base64 = "0.13.0" base64 = "0.13.0"
thiserror = "1.0.22" thiserror = "1.0.22"
tokio = { version = "0.2.22", features = ["full"] }

View File

@ -4,12 +4,16 @@ use std::{
}, },
iter::FromIterator, iter::FromIterator,
sync::{ sync::{
Mutex,
MutexGuard, MutexGuard,
PoisonError, PoisonError,
}, },
}; };
use tokio::{
runtime::Runtime,
sync::Mutex,
};
pub struct Store { pub struct Store {
status_dirs: HashMap <Vec <u8>, StatusKeyDirectory>, status_dirs: HashMap <Vec <u8>, StatusKeyDirectory>,
} }
@ -59,22 +63,22 @@ impl Store {
.collect () .collect ()
} }
pub fn set (&self, name: &[u8], key: Vec <u8>, value: Vec <u8>) pub async fn set (&self, name: &[u8], key: Vec <u8>, value: Vec <u8>)
-> Result <(), Error> -> Result <(), Error>
{ {
let dir = self.status_dirs.get (name) let dir = self.status_dirs.get (name)
.ok_or (Error::NoSuchKeyDir)?; .ok_or (Error::NoSuchKeyDir)?;
dir.set (key, value) dir.set (key, value).await
} }
pub fn get_after (&self, name: &[u8], thresh: Option <u64>) pub async fn get_after (&self, name: &[u8], thresh: Option <u64>)
-> Result <GetAfter, Error> -> Result <GetAfter, Error>
{ {
let dir = self.status_dirs.get (name) let dir = self.status_dirs.get (name)
.ok_or (Error::NoSuchKeyDir)?; .ok_or (Error::NoSuchKeyDir)?;
dir.get_after (thresh) dir.get_after (thresh).await
} }
} }
@ -123,7 +127,7 @@ impl StatusKeyDirectory {
} }
} }
fn set (&self, key: Vec <u8>, value: Vec <u8>) -> Result <(), Error> async fn set (&self, key: Vec <u8>, value: Vec <u8>) -> Result <(), Error>
{ {
if key.len () > self.quotas.max_key_bytes { if key.len () > self.quotas.max_key_bytes {
return Err (Error::KeyTooLong); return Err (Error::KeyTooLong);
@ -134,14 +138,14 @@ impl StatusKeyDirectory {
} }
{ {
let mut guard = self.table.lock ()?; let mut guard = self.table.lock ().await;
guard.set (&self.quotas, key, value); guard.set (&self.quotas, key, value);
} }
Ok (()) Ok (())
} }
fn get_after (&self, thresh: Option <u64>) -> Result <GetAfter, Error> { async fn get_after (&self, thresh: Option <u64>) -> Result <GetAfter, Error> {
let guard = self.table.lock ()?; let guard = self.table.lock ().await;
Ok (guard.get_after (thresh)) Ok (guard.get_after (thresh))
} }
} }
@ -222,6 +226,8 @@ mod tests {
#[test] #[test]
fn store () { fn store () {
let mut rt = Runtime::new ().unwrap ();
rt.block_on (async {
let s = Store::new (vec! [ let s = Store::new (vec! [
(b"key_dir".to_vec (), StatusQuotas { (b"key_dir".to_vec (), StatusQuotas {
max_keys: 4, max_keys: 4,
@ -238,25 +244,25 @@ mod tests {
]); ]);
assert_eq! ( assert_eq! (
s.set (b"key_dir", b"this key is too long and will cause an error".to_vec (), b"bar".to_vec ()), s.set (b"key_dir", b"this key is too long and will cause an error".to_vec (), b"bar".to_vec ()).await,
Err (Error::KeyTooLong) Err (Error::KeyTooLong)
); );
assert_eq! ( assert_eq! (
s.set (b"key_dir", b"foo".to_vec (), b"this value is too long and will cause an error".to_vec ()), s.set (b"key_dir", b"foo".to_vec (), b"this value is too long and will cause an error".to_vec ()).await,
Err (Error::ValueTooLong) Err (Error::ValueTooLong)
); );
assert_eq! ( assert_eq! (
s.set (b"invalid_key_dir", b"foo".to_vec (), b"bar".to_vec ()), s.set (b"invalid_key_dir", b"foo".to_vec (), b"bar".to_vec ()).await,
Err (Error::NoSuchKeyDir) Err (Error::NoSuchKeyDir)
); );
let ga = s.get_after (b"key_dir", None).unwrap (); let ga = s.get_after (b"key_dir", None).await.unwrap ();
assert_eq! (ga.sequence, expected_sequence); assert_eq! (ga.sequence, expected_sequence);
assert_eq! (ga.tuples, vec! []); assert_eq! (ga.tuples, vec! []);
s.set (b"key_dir", b"foo_1".to_vec (), b"bar_1".to_vec ()).unwrap (); s.set (b"key_dir", b"foo_1".to_vec (), b"bar_1".to_vec ()).await.unwrap ();
expected_sequence += 1; expected_sequence += 1;
let ga = s.get_after (b"key_dir", None).unwrap (); let ga = s.get_after (b"key_dir", None).await.unwrap ();
assert_eq! (ga.sequence, expected_sequence); assert_eq! (ga.sequence, expected_sequence);
assert_eq! (ga.tuples, vec! [ assert_eq! (ga.tuples, vec! [
@ -270,9 +276,9 @@ mod tests {
] ]
}); });
s.set (b"key_dir", b"foo_2".to_vec (), b"bar_2".to_vec ()).unwrap (); s.set (b"key_dir", b"foo_2".to_vec (), b"bar_2".to_vec ()).await.unwrap ();
expected_sequence += 1; expected_sequence += 1;
let ga = s.get_after (b"key_dir", None).unwrap (); let ga = s.get_after (b"key_dir", None).await.unwrap ();
get_after_eq (&ga, &GetAfter { get_after_eq (&ga, &GetAfter {
sequence: expected_sequence, sequence: expected_sequence,
@ -282,9 +288,9 @@ mod tests {
] ]
}); });
s.set (b"key_dir", b"foo_1".to_vec (), b"bar_3".to_vec ()).unwrap (); s.set (b"key_dir", b"foo_1".to_vec (), b"bar_3".to_vec ()).await.unwrap ();
expected_sequence += 1; expected_sequence += 1;
let ga = s.get_after (b"key_dir", None).unwrap (); let ga = s.get_after (b"key_dir", None).await.unwrap ();
get_after_eq (&ga, &GetAfter { get_after_eq (&ga, &GetAfter {
sequence: expected_sequence, sequence: expected_sequence,
@ -294,7 +300,7 @@ mod tests {
] ]
}); });
let ga = s.get_after (b"key_dir", Some (2)).unwrap (); let ga = s.get_after (b"key_dir", Some (2)).await.unwrap ();
get_after_eq (&ga, &GetAfter { get_after_eq (&ga, &GetAfter {
sequence: expected_sequence, sequence: expected_sequence,
tuples: vec! [ tuples: vec! [
@ -302,11 +308,12 @@ mod tests {
] ]
}); });
let ga = s.get_after (b"key_dir", Some (3)).unwrap (); let ga = s.get_after (b"key_dir", Some (3)).await.unwrap ();
get_after_eq (&ga, &GetAfter { get_after_eq (&ga, &GetAfter {
sequence: expected_sequence, sequence: expected_sequence,
tuples: vec! [] tuples: vec! []
}); });
});
} }
#[test] #[test]
@ -314,6 +321,8 @@ mod tests {
fn perf () { fn perf () {
use std::time::Instant; use std::time::Instant;
let mut rt = Runtime::new ().unwrap ();
rt.block_on (async {
let s = Store::new (vec! [ let s = Store::new (vec! [
(b"key_dir".to_vec (), StatusQuotas { (b"key_dir".to_vec (), StatusQuotas {
max_keys: 4, max_keys: 4,
@ -332,7 +341,7 @@ mod tests {
for i in 0..num_iters { for i in 0..num_iters {
let value = format! ("{}", i); let value = format! ("{}", i);
s.set (b"key_dir", key.clone (), value.into ()); s.set (b"key_dir", key.clone (), value.into ()).await.unwrap ();
} }
let end_time = Instant::now (); let end_time = Instant::now ();
@ -340,6 +349,7 @@ mod tests {
let avg_nanos = total_dur.as_nanos () / num_iters; let avg_nanos = total_dur.as_nanos () / num_iters;
assert! (avg_nanos < 200); assert! (avg_nanos < 300, dbg! (avg_nanos));
});
} }
} }