Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 21aa65d

Browse files
committed
Trigger gc based on constant rule.
1 parent b8564e6 commit 21aa65d

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-1
lines changed

core/state-machine/src/changes_trie/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ mod test {
259259
])),
260260
].into_iter().collect(),
261261
},
262+
operation_from_last_gc: 0,
262263
};
263264

264265
(backend, storage, changes)

core/state-machine/src/ext.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ mod tests {
380380
])),
381381
].into_iter().collect(),
382382
},
383+
operation_from_last_gc: 0,
383384
}
384385
}
385386

core/state-machine/src/overlayed_changes.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,25 @@ pub(crate) enum TransactionState {
4444
Dropped,
4545
}
4646

47+
48+
/// Treshold of operation before running a garbage colletion
49+
/// on a transaction operation.
50+
/// Should be same as `TRIGGER_COMMIT_GC` or higher
51+
/// (we most likely do not want lower as transaction are
52+
/// possibly more frequent than commit).
53+
const TRIGGER_TRANSACTION_GC: usize = 10_000;
54+
55+
/// Treshold of operation before running a garbage colletion
56+
/// on a commit operation.
57+
/// We may want a lower value than for a transaction, even
58+
/// a 1 if we want to do it between every operation.
59+
const TRIGGER_COMMIT_GC: usize = 1_000;
60+
61+
/// Used to count big content as multiple operation.
62+
/// This is a number of octet.
63+
/// Set to 0 to ignore.
64+
const ADD_CONTENT_SIZE_UNIT: usize = 64;
65+
4766
/// The overlayed changes to state to be queried on top of the backend.
4867
///
4968
/// A transaction shares all prospective changes within an inner overlay
@@ -55,6 +74,10 @@ pub struct OverlayedChanges {
5574
/// Changes trie configuration. None by default, but could be installed by the
5675
/// runtime if it supports change tries.
5776
pub(crate) changes_trie_config: Option<ChangesTrieConfig>,
77+
/// Counter of number of operation between garbage collection.
78+
/// Add or delete cost one, additional cost per size by counting a fix size
79+
/// as a unit.
80+
pub(crate) operation_from_last_gc: usize,
5881
}
5982

6083
/// The storage value, used inside OverlayedChanges.
@@ -683,10 +706,18 @@ impl OverlayedChanges {
683706
None
684707
}
685708

709+
fn add_cost_op(&mut self, val: &Option<Vec<u8>>) {
710+
let content_cost = if ADD_CONTENT_SIZE_UNIT > 0 {
711+
val.as_ref().map(|s| s.len() / ADD_CONTENT_SIZE_UNIT).unwrap_or(0)
712+
} else { 0 };
713+
self.operation_from_last_gc += 1 + content_cost;
714+
}
715+
686716
/// Inserts the given key-value pair into the prospective change set.
687717
///
688718
/// `None` can be used to delete a value specified by the given key.
689719
pub fn set_storage(&mut self, key: Vec<u8>, val: Option<Vec<u8>>) {
720+
self.add_cost_op(&val);
690721
let extrinsic_index = self.extrinsic_index();
691722
let entry = self.changes.top.entry(key).or_default();
692723
entry.set_with_extrinsic(self.changes.history.as_slice(), val, extrinsic_index);
@@ -696,6 +727,7 @@ impl OverlayedChanges {
696727
///
697728
/// `None` can be used to delete a value specified by the given key.
698729
pub(crate) fn set_child_storage(&mut self, storage_key: Vec<u8>, key: Vec<u8>, val: Option<Vec<u8>>) {
730+
self.add_cost_op(&val);
699731
let extrinsic_index = self.extrinsic_index();
700732
let map_entry = self.changes.children.entry(storage_key).or_default();
701733
let entry = map_entry.entry(key).or_default();
@@ -713,6 +745,7 @@ impl OverlayedChanges {
713745
let history = self.changes.history.as_slice();
714746
let map_entry = self.changes.children.entry(storage_key.to_vec()).or_default();
715747

748+
self.operation_from_last_gc += map_entry.len();
716749
map_entry.values_mut().for_each(|e| e.set_with_extrinsic(history, None, extrinsic_index));
717750
}
718751

@@ -725,32 +758,52 @@ impl OverlayedChanges {
725758
pub(crate) fn clear_prefix(&mut self, prefix: &[u8]) {
726759
let extrinsic_index = self.extrinsic_index();
727760

761+
let mut nb_remove = 0;
728762
for (key, entry) in self.changes.top.iter_mut() {
729763
if key.starts_with(prefix) {
764+
nb_remove += 1;
730765
entry.set_with_extrinsic(self.changes.history.as_slice(), None, extrinsic_index);
731766
}
732767
}
768+
769+
self.operation_from_last_gc += nb_remove;
733770
}
734771

735772
/// Discard prospective changes to state.
736773
pub fn discard_prospective(&mut self) {
737774
self.changes.discard_prospective();
775+
if self.operation_from_last_gc > TRIGGER_COMMIT_GC {
776+
self.operation_from_last_gc = 0;
777+
self.gc(true);
778+
}
738779
}
739780

740781
/// Commit prospective changes to state.
741782
pub fn commit_prospective(&mut self) {
742783
self.changes.commit_prospective();
784+
if self.operation_from_last_gc > TRIGGER_COMMIT_GC {
785+
self.operation_from_last_gc = 0;
786+
self.gc(true);
787+
}
743788
}
744789

745790
/// Create a new transactional layer.
746791
pub fn start_transaction(&mut self) {
747792
self.changes.start_transaction();
793+
if self.operation_from_last_gc > TRIGGER_TRANSACTION_GC {
794+
self.operation_from_last_gc = 0;
795+
self.gc(true);
796+
}
748797
}
749798

750799
/// Discard a transactional layer.
751800
/// A transaction is always running (history always end with pending).
752801
pub fn discard_transaction(&mut self) {
753802
self.changes.discard_transaction();
803+
if self.operation_from_last_gc > TRIGGER_TRANSACTION_GC {
804+
self.operation_from_last_gc = 0;
805+
self.gc(true);
806+
}
754807
}
755808

756809
/// Commit a transactional layer.
@@ -803,7 +856,11 @@ impl OverlayedChanges {
803856
changes_trie_config: Option<ChangesTrieConfig>,
804857
) -> Self {
805858
let changes = OverlayedChangeSet::default();
806-
let mut result = OverlayedChanges { changes, changes_trie_config };
859+
let mut result = OverlayedChanges {
860+
changes,
861+
changes_trie_config,
862+
operation_from_last_gc: 0,
863+
};
807864
committed.into_iter().for_each(|(k, v)| result.set_storage(k, v));
808865
result.changes.commit_prospective();
809866
prospective.into_iter().for_each(|(k, v)| result.set_storage(k, v));

0 commit comments

Comments
 (0)