diff --git a/Cargo.lock b/Cargo.lock index 7e9aa99d..33262c10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -216,6 +216,21 @@ dependencies = [ "syn 1.0.100", ] +[[package]] +name = "dhat" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0684eaa19a59be283a6f99369917b679bd4d1d06604b2eb2e2f87b4bbd67668d" +dependencies = [ + "backtrace", + "lazy_static", + "parking_lot", + "rustc-hash", + "serde", + "serde_json", + "thousands", +] + [[package]] name = "digest" version = "0.10.5" @@ -327,6 +342,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "itoa" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" + [[package]] name = "js-sys" version = "0.3.60" @@ -377,6 +398,7 @@ dependencies = [ "colored", "crdt-list", "ctor", + "dhat", "enum-as-inner", "fxhash", "im", @@ -843,6 +865,12 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rusty-fork" version = "0.3.0" @@ -855,6 +883,12 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + [[package]] name = "scopeguard" version = "1.1.0" @@ -881,6 +915,17 @@ dependencies = [ "syn 1.0.100", ] +[[package]] +name = "serde_json" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha2" version = "0.10.6" @@ -1046,6 +1091,12 @@ dependencies = [ "syn 1.0.100", ] +[[package]] +name = "thousands" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" + [[package]] name = "typenum" version = "1.15.0" diff --git a/Cargo.toml b/Cargo.toml index c66a4d73..6f6c1572 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,5 @@ [workspace] members = ["crates/*"] + +[profile.release] +debug = 1 diff --git a/crates/loro-core/Cargo.toml b/crates/loro-core/Cargo.toml index f6dcf975..dcfe8164 100644 --- a/crates/loro-core/Cargo.toml +++ b/crates/loro-core/Cargo.toml @@ -27,6 +27,7 @@ colored = "2.0.0" bit-vec = "0.6.3" [dev-dependencies] +dhat = "0.3.1" rand = { version = "0.8.5" } proptest = "1.0.0" proptest-derive = "0.3.0" @@ -42,5 +43,5 @@ doctest = false [features] # whether to use list slice instead of raw str in text container slice = [] -fuzzing = ["crdt-list/fuzzing", "slice", "rand", "arbitrary", "tabled"] +fuzzing = ["crdt-list/fuzzing", "rand", "slice", "arbitrary", "tabled"] proptest = ["fuzzing"] diff --git a/crates/loro-core/examples/test.rs b/crates/loro-core/examples/test.rs index eaa5df70..3368473a 100644 --- a/crates/loro-core/examples/test.rs +++ b/crates/loro-core/examples/test.rs @@ -1,29 +1,178 @@ +use std::{cell::RefCell, rc::Rc}; + #[cfg(not(feature = "fuzzing"))] fn main() {} +struct Ref { + out: Option>>, +} + #[cfg(feature = "fuzzing")] fn main() { - use crdt_list::test; - use crdt_list::test::Action::*; - use loro_core::container::text::tracker::yata_impl::YataImpl; - let mut actions = vec![]; - for i in 0..500_usize { - actions.push(if i % 2 == 0 { - NewOp { - client_id: i as u8, - pos: i as u8, - } - } else { - Delete { - client_id: i as u8, - pos: i as u8, - len: (i + 1) as u8, - } - }) - } + use std::cell::RefCell; + use std::rc::Rc; - for _ in 0..1000 { - test::test_with_actions::(5, 100, actions.clone()); + use loro_core::fuzz::test_multi_sites; + use loro_core::fuzz::Action::*; + + // let mut a = Rc::new(RefCell::new(Ref { out: None })); + // let mut b = Rc::new(RefCell::new(Ref { + // out: Some(a.clone()), + // })); + // a.borrow_mut().out = Some(b.clone()); + for _ in 0..1 { + test_multi_sites( + 10, + vec![ + Ins { + content: "012".into(), + pos: 72066424675961795, + site: 195, + }, + Ins { + content: "333".into(), + pos: 827253904285695742, + site: 11, + }, + Ins { + content: "444".into(), + pos: 1941308511220, + site: 6, + }, + Del { + pos: 14052919687256211456, + len: 8863007108820470271, + site: 186, + }, + Ins { + content: "555555555555555555555".into(), + pos: 16176931510800348179, + site: 49, + }, + Ins { + content: "aaa".into(), + pos: 1108097569780, + site: 6, + }, + Sync { from: 255, to: 16 }, + Del { + pos: 19, + len: 4, + site: 31, + }, + Sync { from: 255, to: 16 }, + Del { + pos: 19, + len: 4, + site: 31, + }, + Ins { + content: "x".into(), + pos: 320012288, + site: 0, + }, + Ins { + content: "012".into(), + pos: 72066424675961795, + site: 195, + }, + Ins { + content: "333".into(), + pos: 827253904285695742, + site: 11, + }, + Ins { + content: "444".into(), + pos: 1941308511220, + site: 6, + }, + Del { + pos: 14052919687256211456, + len: 8863007108820470271, + site: 186, + }, + Ins { + content: "012".into(), + pos: 72066424675961795, + site: 195, + }, + Ins { + content: "333".into(), + pos: 827253904285695742, + site: 11, + }, + Ins { + content: "444".into(), + pos: 1941308511220, + site: 6, + }, + Del { + pos: 14052919687256211456, + len: 8863007108820470271, + site: 186, + }, + Ins { + content: "012".into(), + pos: 72066424675961795, + site: 195, + }, + Ins { + content: "333".into(), + pos: 827253904285695742, + site: 11, + }, + Ins { + content: "444".into(), + pos: 1941308511220, + site: 6, + }, + Del { + pos: 14052919687256211456, + len: 8863007108820470271, + site: 186, + }, + Ins { + content: "012".into(), + pos: 72066424675961795, + site: 195, + }, + Ins { + content: "333".into(), + pos: 827253904285695742, + site: 11, + }, + Ins { + content: "444".into(), + pos: 1941308511220, + site: 6, + }, + Del { + pos: 14052919687256211456, + len: 8863007108820470271, + site: 186, + }, + Ins { + content: "012".into(), + pos: 72066424675961795, + site: 195, + }, + Ins { + content: "333".into(), + pos: 827253904285695742, + site: 11, + }, + Ins { + content: "444".into(), + pos: 1941308511220, + site: 6, + }, + Del { + pos: 14052919687256211456, + len: 8863007108820470271, + site: 186, + }, + ], + ) } println!("HAHA"); diff --git a/crates/loro-core/src/container/text/tracker/cursor_map.rs b/crates/loro-core/src/container/text/tracker/cursor_map.rs index caf29ddc..c948ffd4 100644 --- a/crates/loro-core/src/container/text/tracker/cursor_map.rs +++ b/crates/loro-core/src/container/text/tracker/cursor_map.rs @@ -237,8 +237,10 @@ pub enum FirstCursorResult { impl CursorMap { // FIXME: pub fn get_cursors_at_id_span(&self, span: IdSpan) -> IdSpanQueryResult { - let mut inserts: Vec<(ID, UnsafeCursor<'static, YSpan, YSpanTreeTrait>)> = Vec::new(); - let mut deletes: Vec<(ID, RleVecWithLen<[IdSpan; 2]>)> = Vec::new(); + let mut inserts: Vec<(ID, UnsafeCursor<'static, YSpan, YSpanTreeTrait>)> = + Vec::with_capacity(span.atom_len() / 10); + let mut deletes: Vec<(ID, RleVecWithLen<[IdSpan; 2]>)> = + Vec::with_capacity(span.atom_len() / 10); let mut inserted_set = fxhash::FxHashSet::default(); for (id, marker) in self.get_range_with_index(span.min_id().into(), span.end_id().into()) { let id: ID = id.into(); diff --git a/crates/loro-core/src/dag.rs b/crates/loro-core/src/dag.rs index dc99bd49..635aee1c 100644 --- a/crates/loro-core/src/dag.rs +++ b/crates/loro-core/src/dag.rs @@ -189,7 +189,7 @@ where return vv; } - let mut stack = Vec::new(); + let mut stack = Vec::with_capacity(node.deps().len()); for dep in node.deps() { stack.push(dep); } diff --git a/crates/loro-core/src/fuzz.rs b/crates/loro-core/src/fuzz.rs index df168acd..254425a9 100644 --- a/crates/loro-core/src/fuzz.rs +++ b/crates/loro-core/src/fuzz.rs @@ -1,4 +1,3 @@ -use arbitrary::Arbitrary; use enum_as_inner::EnumAsInner; use tabled::{TableIteratorExt, Tabled}; diff --git a/crates/loro-core/src/log_store.rs b/crates/loro-core/src/log_store.rs index 64820d3a..43dee491 100644 --- a/crates/loro-core/src/log_store.rs +++ b/crates/loro-core/src/log_store.rs @@ -128,7 +128,7 @@ impl LogStore { fn get_changes_slice(&self, id_span: IdSpan) -> Vec { if let Some(changes) = self.changes.get(&id_span.client_id) { - let mut ans = Vec::new(); + let mut ans = Vec::with_capacity(id_span.atom_len() / 30); for change in changes.slice_iter( id_span.counter.min() as usize, id_span.counter.end() as usize, diff --git a/crates/rle/src/rle_tree/node/internal_impl.rs b/crates/rle/src/rle_tree/node/internal_impl.rs index c63f7899..92890579 100644 --- a/crates/rle/src/rle_tree/node/internal_impl.rs +++ b/crates/rle/src/rle_tree/node/internal_impl.rs @@ -3,7 +3,7 @@ use std::{ fmt::{Debug, Error, Formatter}, }; -use fxhash::FxHashSet; +use fxhash::{FxBuildHasher, FxHashSet, FxHasher}; use crate::rle_tree::{ node::utils::distribute, @@ -275,8 +275,11 @@ impl<'a, T: Rle, A: RleTreeTrait> InternalNode<'a, T, A> { } updates.sort_by_key(|x| x.0); - let mut new_children: Vec<&'a mut Node<'a, T, A>> = Vec::new(); - let mut self_children = std::mem::replace(&mut self.children, BumpVec::new_in(self.bump)); + let mut new_children: Vec<&'a mut Node<'a, T, A>> = Vec::with_capacity(A::MAX_CHILDREN_NUM); + let mut self_children = std::mem::replace( + &mut self.children, + BumpVec::with_capacity_in(A::MAX_CHILDREN_NUM, self.bump), + ); let mut saved_end = 0; for (index, replace) in updates { for child in self_children.drain(0..index + 1 - saved_end) { @@ -518,7 +521,7 @@ impl<'a, T: Rle, A: RleTreeTrait> InternalNode<'a, T, A> { F: FnMut(&T, *mut LeafNode<'_, T, A>), { debug_assert!(self.is_root()); - let mut zipper = Vec::new(); + let mut zipper = Vec::with_capacity(8); match self._delete(start, end, &mut zipper, 1, notify) { Ok(_) => { A::update_cache_internal(self); @@ -533,8 +536,10 @@ impl<'a, T: Rle, A: RleTreeTrait> InternalNode<'a, T, A> { let removed = self._root_shrink_levels_if_one_child(); // filter the same - let mut visited: HashSet, _> = FxHashSet::default(); - let mut should_skip: HashSet, _> = FxHashSet::default(); + let mut visited: HashSet, _> = + HashSet::with_capacity_and_hasher(zipper.len(), FxBuildHasher::default()); + let mut should_skip: HashSet, _> = + HashSet::with_capacity_and_hasher(zipper.len(), FxBuildHasher::default()); let mut zipper: Vec<(usize, NonNull>)> = zipper .into_iter() .filter(|(_, ptr)| {