From a8ece757e4017f28348ba0d18d45b0173a8f3e85 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 18 May 2021 11:31:40 +0200 Subject: [PATCH] Implement time::Global using a SmallVec Version vectors are going to be small most of the time, especially as soon as we introduce an optimization that will let us only track concurrent versions, thus preventing the version vector from growing indefinitely over time in the tree. --- gpui/Cargo.toml | 2 +- zed/Cargo.toml | 2 +- zed/src/time.rs | 64 +++++++++++++++++++------------------------------ 3 files changed, 26 insertions(+), 42 deletions(-) diff --git a/gpui/Cargo.toml b/gpui/Cargo.toml index d421a5a2f3fd2e59bcc8fd436705a4ea08dec98d..1eba8612bfa9c2474ca5a0e389bf0824cba6479f 100644 --- a/gpui/Cargo.toml +++ b/gpui/Cargo.toml @@ -23,7 +23,7 @@ scoped-pool = {path = "../scoped_pool"} seahash = "4.1" serde = {version = "1.0.125", features = ["derive"]} serde_json = "1.0.64" -smallvec = "1.6.1" +smallvec = {version = "1.6", features = ["union"]} smol = "1.2" tiny-skia = "0.5" tree-sitter = "0.17" diff --git a/zed/Cargo.toml b/zed/Cargo.toml index 2302fc650954c18cb5ee21b902087436575e8006..a1749f2474930dacb4ba2db0d52b8e7dc9ea4d13 100644 --- a/zed/Cargo.toml +++ b/zed/Cargo.toml @@ -36,7 +36,7 @@ seahash = "4.1" serde = {version = "1", features = ["derive"]} similar = "1.3" simplelog = "0.9" -smallvec = "1.6.1" +smallvec = {version = "1.6", features = ["union"]} smol = "1.2.5" [dev-dependencies] diff --git a/zed/src/time.rs b/zed/src/time.rs index 4836ed921c86b4f1010795cf693b9a76b3f3e7aa..f1cf4eef916c9c7995cbc333a18d3a2d51a1ccd2 100644 --- a/zed/src/time.rs +++ b/zed/src/time.rs @@ -1,13 +1,9 @@ +use smallvec::SmallVec; use std::cmp::{self, Ordering}; -use std::collections::HashMap; -use std::mem; use std::ops::{Add, AddAssign}; -use std::sync::Arc; - -use lazy_static::lazy_static; pub type ReplicaId = u16; -pub type Seq = u64; +pub type Seq = u32; #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd)] pub struct Local { @@ -58,18 +54,8 @@ impl<'a> AddAssign<&'a Local> for Local { } } -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct Global(Arc>); - -lazy_static! { - static ref DEFAULT_GLOBAL: Global = Global(Arc::new(HashMap::new())); -} - -impl Default for Global { - fn default() -> Self { - DEFAULT_GLOBAL.clone() - } -} +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct Global(SmallVec<[Local; 3]>); impl Global { pub fn new() -> Self { @@ -77,21 +63,27 @@ impl Global { } pub fn get(&self, replica_id: ReplicaId) -> Seq { - *self.0.get(&replica_id).unwrap_or(&0) + self.0 + .iter() + .find(|t| t.replica_id == replica_id) + .map_or(0, |t| t.value) } pub fn observe(&mut self, timestamp: Local) { - let map = Arc::make_mut(&mut self.0); - let value = map.entry(timestamp.replica_id).or_insert(0); - *value = cmp::max(*value, timestamp.value); + if let Some(entry) = self + .0 + .iter_mut() + .find(|t| t.replica_id == timestamp.replica_id) + { + entry.value = cmp::max(entry.value, timestamp.value); + } else { + self.0.push(timestamp); + } } pub fn observe_all(&mut self, other: &Self) { - for (replica_id, value) in other.0.as_ref() { - self.observe(Local { - replica_id: *replica_id, - value: *value, - }); + for timestamp in other.0.iter() { + self.observe(*timestamp); } } @@ -100,9 +92,7 @@ impl Global { } pub fn changed_since(&self, other: &Self) -> bool { - self.0 - .iter() - .any(|(replica_id, value)| *value > other.get(*replica_id)) + self.0.iter().any(|t| t.value > other.get(t.replica_id)) } } @@ -110,8 +100,10 @@ impl PartialOrd for Global { fn partial_cmp(&self, other: &Self) -> Option { let mut global_ordering = Ordering::Equal; - for replica_id in self.0.keys().chain(other.0.keys()) { - let ordering = self.get(*replica_id).cmp(&other.get(*replica_id)); + for timestamp in self.0.iter().chain(other.0.iter()) { + let ordering = self + .get(timestamp.replica_id) + .cmp(&other.get(timestamp.replica_id)); if ordering != Ordering::Equal { if global_ordering == Ordering::Equal { global_ordering = ordering; @@ -142,12 +134,4 @@ impl Lamport { pub fn observe(&mut self, timestamp: Self) { self.value = cmp::max(self.value, timestamp.value) + 1; } - - pub fn to_bytes(&self) -> [u8; 24] { - let mut bytes = [0; 24]; - bytes[0..8].copy_from_slice(unsafe { &mem::transmute::(self.value.to_be()) }); - bytes[8..10] - .copy_from_slice(unsafe { &mem::transmute::(self.replica_id.to_be()) }); - bytes - } }