Skip to content

Add optional features that can potentially improve performance #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 24, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,12 @@ travis-ci = { repository = "jonhoo/rust-evmap" }
maintenance = { status = "passively-maintained" }

[dependencies]
hashbrown = { version = "0.1.8", optional = true }
parking_lot = { version = "0.7.1", optional = true }
smallvec = { version = "0.6.7", optional = true }

[features]
default = []
nightly_hashbrown = ["hashbrown/nightly"]
nightly_parking_lot = ["parking_lot/nightly"]
nightly_smallvec = ["smallvec/union"]
14 changes: 12 additions & 2 deletions benchmark/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,21 @@ version = "0.1.0"
authors = ["Jon Gjengset <[email protected]>"]

[dependencies]
evmap = { path = "../" }
evmap = { path = "../", features = ["hashbrown", "parking_lot", "smallvec"] }
chashmap = "2.1.0"
clap = "2.20.3"
zipf = "0.2.0"
rand = "0.3"
parking_lot = "0.7.1"

[target.'cgf(not(target_env = "msvc"))'.dependencies]
jemallocator = {version = "0.1.9", optional = true }

[profile.release]
debug = true
lto = true
opt-level = 3
codegen-units = 1
debug = false

[features]
nightly = ["evmap/nightly_hashbrown", "evmap/nightly_parking_lot", "evmap/nightly_smallvec", "jemallocator"]
14 changes: 11 additions & 3 deletions benchmark/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ extern crate clap;
extern crate evmap;
extern crate rand;
extern crate zipf;
extern crate parking_lot;

#[cfg(all(not(target_env = "msvc"), feature = "nightly"))]
extern crate jemallocator;

#[cfg(all(not(target_env = "msvc"), feature = "nightly"))]
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

use chashmap::CHashMap;
use std::collections::HashMap;
Expand Down Expand Up @@ -135,7 +143,7 @@ fn main() {
let (r, w) = evmap::Options::default()
.with_capacity(5_000_000)
.construct();
let w = sync::Arc::new(sync::Mutex::new((w, 0, refresh)));
let w = sync::Arc::new(parking_lot::Mutex::new((w, 0, refresh)));
let start = time::Instant::now();
let end = start + dur;
join.extend((0..readers).into_iter().map(|_| {
Expand Down Expand Up @@ -218,7 +226,7 @@ impl Backend for sync::Arc<sync::RwLock<HashMap<u64, u64>>> {

enum EvHandle {
Read(evmap::ReadHandle<u64, u64>),
Write(sync::Arc<sync::Mutex<(evmap::WriteHandle<u64, u64>, usize, usize)>>),
Write(sync::Arc<parking_lot::Mutex<(evmap::WriteHandle<u64, u64>, usize, usize)>>),
}

impl Backend for EvHandle {
Expand All @@ -232,7 +240,7 @@ impl Backend for EvHandle {

fn b_put(&mut self, key: u64, value: u64) {
if let EvHandle::Write(ref w) = *self {
let mut w = w.lock().unwrap();
let mut w = w.lock();
w.0.update(key, value);
w.1 += 1;
if w.1 == w.2 {
Expand Down
21 changes: 19 additions & 2 deletions src/inner.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
#[cfg(not(feature = "hashbrown"))]
use std::collections::HashMap;

#[cfg(feature = "hashbrown")]
use hashbrown::HashMap;

use std::hash::{BuildHasher, Hash};
use std::sync::{atomic, Arc, Mutex};
use std::sync::{atomic, Arc};

#[cfg(not(feature = "parking_lot"))]
use std::sync::Mutex;

#[cfg(feature = "parking_lot")]
use parking_lot::Mutex;

#[cfg(not(feature = "smallvec"))]
pub(crate) type Log<T> = Vec<T>;

#[cfg(feature = "smallvec")]
pub(crate) type Log<T> = smallvec::SmallVec<[T; 1]>;

pub(crate) struct Inner<K, V, M, S>
where
K: Eq + Hash,
S: BuildHasher,
{
pub(crate) data: HashMap<K, Vec<V>, S>,
pub(crate) data: HashMap<K, Log<V>, S>,
pub(crate) epochs: Arc<Mutex<Vec<Arc<atomic::AtomicUsize>>>>,
pub(crate) meta: M,
ready: bool,
Expand Down
30 changes: 23 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,23 @@
//!
#![deny(missing_docs)]

use std::collections::hash_map::RandomState;
#[cfg(feature = "parking_lot")]
extern crate parking_lot;

#[cfg(feature = "hashbrown")]
extern crate hashbrown;

#[cfg(feature = "smallvec")]
extern crate smallvec;

/// Re-export default hash builder
#[cfg(feature = "hashbrown")]
pub type DefaultHashBuilder = hashbrown::hash_map::DefaultHashBuilder;

/// Re-export default hash builder
#[cfg(not(feature = "hashbrown"))]
pub type DefaultHashBuilder = std::collections::hash_map::RandomState;

use std::hash::{BuildHasher, Hash};

mod inner;
Expand Down Expand Up @@ -227,11 +243,11 @@ where
capacity: Option<usize>,
}

impl Default for Options<(), RandomState> {
impl Default for Options<(), DefaultHashBuilder> {
fn default() -> Self {
Options {
meta: (),
hasher: RandomState::default(),
hasher: DefaultHashBuilder::default(),
capacity: None,
}
}
Expand Down Expand Up @@ -297,8 +313,8 @@ where
/// Create an empty eventually consistent map.
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
pub fn new<K, V>() -> (
ReadHandle<K, V, (), RandomState>,
WriteHandle<K, V, (), RandomState>,
ReadHandle<K, V, (), DefaultHashBuilder>,
WriteHandle<K, V, (), DefaultHashBuilder>,
)
where
K: Eq + Hash + Clone,
Expand All @@ -312,8 +328,8 @@ where
pub fn with_meta<K, V, M>(
meta: M,
) -> (
ReadHandle<K, V, M, RandomState>,
WriteHandle<K, V, M, RandomState>,
ReadHandle<K, V, M, DefaultHashBuilder>,
WriteHandle<K, V, M, DefaultHashBuilder>,
)
where
K: Eq + Hash + Clone,
Expand Down
34 changes: 27 additions & 7 deletions src/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use inner::Inner;

use std::borrow::Borrow;
use std::cell;
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hash};
use std::iter::{self, FromIterator};
use std::marker::PhantomData;
Expand All @@ -11,12 +10,14 @@ use std::sync::atomic;
use std::sync::atomic::AtomicPtr;
use std::sync::{self, Arc};

use super::DefaultHashBuilder;

/// A handle that may be used to read from the eventually consistent map.
///
/// Note that any changes made to the map will not be made visible until the writer calls
/// `refresh()`. In other words, all operations performed on a `ReadHandle` will *only* see writes
/// to the map that preceeded the last call to `refresh()`.
pub struct ReadHandle<K, V, M = (), S = RandomState>
pub struct ReadHandle<K, V, M = (), S = DefaultHashBuilder>
where
K: Eq + Hash,
S: BuildHasher,
Expand Down Expand Up @@ -59,9 +60,19 @@ where
{
// tell writer about our epoch tracker
let epoch = sync::Arc::new(atomic::AtomicUsize::new(0));
inner.epochs.lock().unwrap().push(Arc::clone(&epoch));

{
#[cfg(not(feature = "parking_lot"))]
let mut epochs = inner.epochs.lock().unwrap();

#[cfg(feature = "parking_lot")]
let mut epochs = inner.epochs.lock();

epochs.push(Arc::clone(&epoch));
}

let store = Box::into_raw(Box::new(inner));

ReadHandle {
epoch: epoch,
my_epoch: atomic::AtomicUsize::new(0),
Expand All @@ -78,7 +89,13 @@ where
{
fn register_epoch(&self, epoch: &Arc<atomic::AtomicUsize>) {
if let Some(epochs) = self.with_handle(|inner| Arc::clone(&inner.epochs)) {
epochs.lock().unwrap().push(Arc::clone(epoch));
#[cfg(not(feature = "parking_lot"))]
let mut epochs = epochs.lock().unwrap();

#[cfg(feature = "parking_lot")]
let mut epochs = epochs.lock();

epochs.push(Arc::clone(epoch));
}
}

Expand Down Expand Up @@ -177,7 +194,8 @@ where
} else {
inner.data.get(key).map(move |v| then(&**v))
}
}).unwrap_or(None)
})
.unwrap_or(None)
}

/// Applies a function to the values corresponding to the key, and returns the result alongside
Expand Down Expand Up @@ -206,7 +224,8 @@ where
let res = (res, inner.meta.clone());
Some(res)
}
}).unwrap_or(None)
})
.unwrap_or(None)
}

/// If the writer has destroyed this map, this method will return true.
Expand Down Expand Up @@ -252,6 +271,7 @@ where
{
self.with_handle(move |inner| {
Collector::from_iter(inner.data.iter().map(|(k, vs)| f(k, &vs[..])))
}).unwrap_or(Collector::from_iter(iter::empty()))
})
.unwrap_or_else(|| Collector::from_iter(iter::empty()))
}
}
Loading