fix: checkout diff-calc cache issue

This commit is contained in:
Zixuan Chen 2024-09-30 16:39:27 +08:00
parent 5688a017d6
commit 37ed452bc5
No known key found for this signature in database
2 changed files with 218 additions and 55 deletions

View file

@ -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![],
)

View file

@ -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,