diff --git a/crates/fuzz/tests/test.rs b/crates/fuzz/tests/test.rs index 2a2d46bf..7aea4a31 100644 --- a/crates/fuzz/tests/test.rs +++ b/crates/fuzz/tests/test.rs @@ -11408,11 +11408,223 @@ fn gc_fuzz_25() { ) } +#[test] +fn gc_fuzz_unknown() { + test_multi_sites( + 5, + vec![FuzzTarget::All], + &mut [ + Handle { + site: 1, + target: 1, + container: 1, + action: Generic(GenericAction { + value: I32(690563377), + bool: true, + key: 690563369, + pos: 2965947086361143593, + length: 2965947086361141289, + prop: 6714067876240238889, + }), + }, + Handle { + site: 41, + target: 41, + container: 41, + action: Generic(GenericAction { + value: I32(690563337), + bool: true, + key: 690563369, + pos: 2965947086361143593, + length: 2965947086361143593, + prop: 18377265011222980905, + }), + }, + SyncAll, + SyncAll, + SyncAll, + SyncAll, + SyncAll, + SyncAll, + SyncAll, + SyncAll, + SyncAll, + Handle { + site: 41, + target: 41, + container: 41, + action: Generic(GenericAction { + value: I32(690563369), + bool: true, + key: 690563369, + pos: 2965947086361143593, + length: 18446472671121713449, + prop: 1297036692682702847, + }), + }, + SyncAll, + SyncAll, + SyncAll, + SyncAll, + Handle { + site: 41, + target: 41, + container: 41, + action: Generic(GenericAction { + value: I32(690563369), + bool: true, + key: 690563369, + pos: 2965947086361143593, + length: 2965937190756493609, + prop: 720339722163530025, + }), + }, + SyncAll, + SyncAll, + SyncAll, + SyncAll, + Handle { + site: 93, + target: 0, + container: 0, + action: Generic(GenericAction { + value: Container(Tree), + bool: false, + key: 690563328, + pos: 2965947086361143593, + length: 2317428740019792169, + prop: 2956940423977314601, + }), + }, + Handle { + site: 41, + target: 41, + container: 93, + action: Generic(GenericAction { + value: Container(Unknown(255)), + bool: true, + key: 4294967295, + pos: 11457157452018352127, + length: 18446743655463952030, + prop: 18446744073709551615, + }), + }, + SyncAll, + Handle { + site: 52, + target: 0, + container: 41, + action: Generic(GenericAction { + value: I32(690563337), + bool: true, + key: 690563369, + pos: 2965947086361143593, + length: 2965947086361143593, + prop: 18446743150982146345, + }), + }, + SyncAll, + Handle { + site: 41, + target: 41, + container: 41, + action: Generic(GenericAction { + value: I32(0), + bool: false, + key: 690563456, + pos: 2965947086361143593, + length: 2965947086360553769, + prop: 18446743017133517097, + }), + }, + SyncAll, + SyncAll, + SyncAll, + Handle { + site: 41, + target: 41, + container: 41, + action: Generic(GenericAction { + value: I32(0), + bool: false, + key: 0, + pos: 2965901829600182272, + length: 2965947086361143593, + prop: 2965947086361143593, + }), + }, + Handle { + site: 41, + target: 32, + container: 41, + action: Generic(GenericAction { + value: Container(Map), + bool: true, + key: 690563369, + pos: 2965947309699442985, + length: 18446744073709551615, + prop: 18446539564546785279, + }), + }, + SyncAllUndo { + site: 158, + op_len: 4294942366, + }, + SyncAll, + Checkout { + site: 0, + to: 690563369, + }, + Handle { + site: 41, + target: 41, + container: 41, + action: Generic(GenericAction { + value: I32(690563369), + bool: true, + key: 690563369, + pos: 2965947086361143593, + length: 18446744073709496617, + prop: 18446744073709551615, + }), + }, + SyncAll, + Handle { + site: 41, + target: 41, + container: 41, + action: Generic(GenericAction { + value: I32(690563369), + bool: true, + key: 690563369, + pos: 2965947086361143593, + length: 3467816969836243241, + prop: 2965911901989054761, + }), + }, + SyncAll, + Handle { + site: 41, + target: 41, + container: 32, + action: Generic(GenericAction { + value: I32(690563369), + bool: true, + key: 4294967049, + pos: 3026418949592973311, + length: 19203147547879721, + prop: 0, + }), + }, + ], + ) +} + #[test] fn minify() { minify_error( 5, - |n, actions| test_multi_sites_with_gc(n, vec![FuzzTarget::All], actions), + |n, actions| test_multi_sites(n, vec![FuzzTarget::All], actions), |_, actions| actions.to_vec(), vec![], ) diff --git a/crates/loro-internal/src/diff_calc.rs b/crates/loro-internal/src/diff_calc.rs index ee44f1dc..8ffc522b 100644 --- a/crates/loro-internal/src/diff_calc.rs +++ b/crates/loro-internal/src/diff_calc.rs @@ -65,7 +65,7 @@ enum DiffCalculatorRetainMode { /// The diff calculator can only be used once. Once { used: bool }, /// The diff calculator will be persisted and can be reused after the diff calc is done. - Persist { recorded_ops_range: VersionRange }, + Persist, } /// This mode defines how the diff is calculated and how it should be applied on the state. @@ -121,9 +121,7 @@ impl DiffCalculator { Self { calculators: Default::default(), retain_mode: if persist { - DiffCalculatorRetainMode::Persist { - recorded_ops_range: Default::default(), - } + DiffCalculatorRetainMode::Persist } else { DiffCalculatorRetainMode::Once { used: false } }, @@ -151,7 +149,6 @@ impl DiffCalculator { let s = tracing::span!(tracing::Level::INFO, "DiffCalc", ?before, ?after,); let _e = s.enter(); - let mut use_persisted_shortcut = false; let mut merged = before.clone(); merged.merge(after); let (lca, mut diff_mode, iter) = @@ -162,34 +159,15 @@ impl DiffCalculator { panic!("DiffCalculator with retain_mode Once can only be used once"); } } - DiffCalculatorRetainMode::Persist { recorded_ops_range } => { - if recorded_ops_range.contains_ops_between(&lca, &merged) - && recorded_ops_range.contains_ops_between(before, after) - { - use_persisted_shortcut = true; - } else { - diff_mode = DiffMode::Checkout; - recorded_ops_range.clear(); - } + DiffCalculatorRetainMode::Persist => { + diff_mode = DiffMode::Checkout; } } - let affected_set = if !use_persisted_shortcut { + let affected_set = { tracing::debug!("LCA: {:?} mode={:?}", &lca, diff_mode); let mut started_set = FxHashSet::default(); for (change, (start_counter, end_counter), vv) in iter { - if let DiffCalculatorRetainMode::Persist { recorded_ops_range } = - &mut self.retain_mode - { - if container_filter.is_none() { - recorded_ops_range.extends_to_include_id_span(IdSpan::new( - change.peer(), - start_counter, - end_counter, - )); - } - } - let iter_start = change .ops .binary_search_by(|op| op.ctr_last().cmp(&start_counter)) @@ -253,33 +231,6 @@ impl DiffCalculator { } Some(started_set) - } else { - debug!("Use persisted shortcut"); - // We can calculate the diff by the current calculators. - - // Find a set of affected containers idx, if it's relatively cheap - if before.distance_between(after) < self.calculators.len() || cfg!(debug_assertions) { - let mut set = FxHashSet::default(); - oplog.for_each_change_within(before, after, |change, (start, end)| { - for op in change.ops.iter() { - if op.ctr_end() <= start || op.ctr_start() >= end { - continue; - } - - let idx = op.container; - if let Some(filter) = container_filter { - if !filter(idx) { - continue; - } - } - - set.insert(op.container); - } - }); - Some(set) - } else { - None - } }; // Because we need to get correct `bring_back` value that indicates container is created during this round of diff calc,