Skip to content

Commit bd4bc78

Browse files
committed
feat(storage): use Once for storage cells
1 parent e85a8ad commit bd4bc78

File tree

1 file changed

+26
-144
lines changed

1 file changed

+26
-144
lines changed

storage/src/store/shard_state/cell_storage.rs

Lines changed: 26 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::cell::UnsafeCell;
22
use std::collections::{hash_map, VecDeque};
33
use std::mem::{ManuallyDrop, MaybeUninit};
4-
use std::sync::atomic::{AtomicI64, AtomicU8, Ordering};
5-
use std::sync::{Arc, Weak};
4+
use std::sync::atomic::{AtomicI64, Ordering};
5+
use std::sync::{Arc, Once, Weak};
66

77
use anyhow::{Context, Result};
88
use bumpalo::Bump;
@@ -632,19 +632,14 @@ pub struct StorageCell {
632632
cell_storage: Arc<CellStorage>,
633633
descriptor: CellDescriptor,
634634
bit_len: u16,
635-
data: Vec<u8>,
636-
hashes: Vec<(HashBytes, u16)>,
635+
data: Box<[u8]>,
636+
hashes: Box<[(HashBytes, u16)]>,
637637

638-
reference_states: [AtomicU8; 4],
638+
reference_states: [Once; 4],
639639
reference_data: [UnsafeCell<StorageCellReferenceData>; 4],
640640
}
641641

642642
impl StorageCell {
643-
const REF_EMPTY: u8 = 0x0;
644-
const REF_RUNNING: u8 = 0x1;
645-
const REF_STORAGE: u8 = 0x2;
646-
const REF_REPLACED: u8 = 0x3;
647-
648643
pub fn deserialize(cell_storage: Arc<CellStorage>, buffer: &[u8]) -> Option<Self> {
649644
if buffer.len() < 4 {
650645
return None;
@@ -661,9 +656,11 @@ impl StorageCell {
661656
return None;
662657
}
663658

664-
let data = buffer[4..4 + byte_len].to_vec();
659+
let data = Box::from(&buffer[4..4 + byte_len]);
660+
661+
let mut hashes = Vec::new();
662+
hashes.reserve_exact(hash_count);
665663

666-
let mut hashes = Vec::with_capacity(hash_count);
667664
let mut offset = 4 + byte_len;
668665
for _ in 0..hash_count {
669666
hashes.push((
@@ -673,7 +670,7 @@ impl StorageCell {
673670
offset += 32 + 2;
674671
}
675672

676-
let reference_states = Default::default();
673+
let reference_states = [(); 4].map(|_| Once::new());
677674
let reference_data = unsafe {
678675
MaybeUninit::<[UnsafeCell<StorageCellReferenceData>; 4]>::uninit().assume_init()
679676
};
@@ -689,7 +686,7 @@ impl StorageCell {
689686
bit_len,
690687
descriptor,
691688
data,
692-
hashes,
689+
hashes: hashes.into_boxed_slice(),
693690
reference_states,
694691
reference_data,
695692
})
@@ -767,88 +764,22 @@ impl StorageCell {
767764
return None;
768765
}
769766

770-
let state = &self.reference_states[index as usize];
771767
let slot = self.reference_data[index as usize].get();
768+
self.reference_states[index as usize].call_once(|| {
769+
let cell = self
770+
.cell_storage
771+
.load_cell(unsafe { (*slot).hash })
772+
.unwrap();
772773

773-
let current_state = state.load(Ordering::Acquire);
774-
if current_state == Self::REF_STORAGE {
775-
return Some(unsafe { &(*slot).storage_cell });
776-
}
777-
778-
let mut res = Ok(());
779-
Self::initialize_inner(state, &mut || match self
780-
.cell_storage
781-
.load_cell(unsafe { (*slot).hash })
782-
{
783-
Ok(cell) => unsafe {
774+
unsafe {
784775
*slot = StorageCellReferenceData {
785776
storage_cell: ManuallyDrop::new(cell),
786-
};
787-
true
788-
},
789-
Err(err) => {
790-
res = Err(err);
791-
false
792-
}
777+
}
778+
};
793779
});
794780

795-
// TODO: just return none?
796-
res.unwrap();
797-
798781
Some(unsafe { &(*slot).storage_cell })
799782
}
800-
801-
fn initialize_inner(state: &AtomicU8, init: &mut impl FnMut() -> bool) {
802-
struct Guard<'a> {
803-
state: &'a AtomicU8,
804-
new_state: u8,
805-
}
806-
807-
impl Drop for Guard<'_> {
808-
fn drop(&mut self) {
809-
self.state.store(self.new_state, Ordering::Release);
810-
unsafe {
811-
let key = self.state as *const AtomicU8 as usize;
812-
parking_lot_core::unpark_all(key, parking_lot_core::DEFAULT_UNPARK_TOKEN);
813-
}
814-
}
815-
}
816-
817-
loop {
818-
let exchange = state.compare_exchange_weak(
819-
Self::REF_EMPTY,
820-
Self::REF_RUNNING,
821-
Ordering::Acquire,
822-
Ordering::Acquire,
823-
);
824-
match exchange {
825-
Ok(_) => {
826-
let mut guard = Guard {
827-
state,
828-
new_state: Self::REF_EMPTY,
829-
};
830-
if init() {
831-
guard.new_state = Self::REF_STORAGE;
832-
}
833-
return;
834-
}
835-
Err(Self::REF_STORAGE) => return,
836-
Err(Self::REF_RUNNING) => unsafe {
837-
let key = state as *const AtomicU8 as usize;
838-
parking_lot_core::park(
839-
key,
840-
|| state.load(Ordering::Relaxed) == Self::REF_RUNNING,
841-
|| (),
842-
|_, _| (),
843-
parking_lot_core::DEFAULT_PARK_TOKEN,
844-
None,
845-
);
846-
},
847-
Err(Self::REF_EMPTY) => (),
848-
Err(_) => debug_assert!(false),
849-
}
850-
}
851-
}
852783
}
853784

854785
impl CellImpl for StorageCell {
@@ -892,48 +823,14 @@ impl CellImpl for StorageCell {
892823
}
893824

894825
fn take_first_child(&mut self) -> Option<Cell> {
895-
let state = self.reference_states[0].swap(Self::REF_EMPTY, Ordering::AcqRel);
896-
let data = self.reference_data[0].get_mut();
897-
match state {
898-
Self::REF_STORAGE => Some(unsafe { data.take_storage_cell() }),
899-
Self::REF_REPLACED => Some(unsafe { data.take_replaced_cell() }),
900-
_ => None,
901-
}
826+
None
902827
}
903828

904829
fn replace_first_child(&mut self, parent: Cell) -> std::result::Result<Cell, Cell> {
905-
let state = self.reference_states[0].load(Ordering::Acquire);
906-
if state < Self::REF_STORAGE {
907-
return Err(parent);
908-
}
909-
910-
self.reference_states[0].store(Self::REF_REPLACED, Ordering::Release);
911-
let data = self.reference_data[0].get_mut();
912-
913-
let cell = match state {
914-
Self::REF_STORAGE => unsafe { data.take_storage_cell() },
915-
Self::REF_REPLACED => unsafe { data.take_replaced_cell() },
916-
_ => return Err(parent),
917-
};
918-
data.replaced_cell = ManuallyDrop::new(parent);
919-
Ok(cell)
830+
Err(parent)
920831
}
921832

922833
fn take_next_child(&mut self) -> Option<Cell> {
923-
while self.descriptor.reference_count() > 1 {
924-
self.descriptor.d1 -= 1;
925-
let idx = (self.descriptor.d1 & CellDescriptor::REF_COUNT_MASK) as usize;
926-
927-
let state = self.reference_states[idx].swap(Self::REF_EMPTY, Ordering::AcqRel);
928-
let data = self.reference_data[idx].get_mut();
929-
930-
return Some(match state {
931-
Self::REF_STORAGE => unsafe { data.take_storage_cell() },
932-
Self::REF_REPLACED => unsafe { data.take_replaced_cell() },
933-
_ => continue,
934-
});
935-
}
936-
937834
None
938835
}
939836

@@ -948,16 +845,13 @@ impl CellImpl for StorageCell {
948845
impl Drop for StorageCell {
949846
fn drop(&mut self) {
950847
self.cell_storage.drop_cell(DynCell::repr_hash(self));
848+
951849
for i in 0..4 {
952-
let state = self.reference_states[i].load(Ordering::Acquire);
850+
let initialized = self.reference_states[i].is_completed();
953851
let data = self.reference_data[i].get_mut();
954852

955-
unsafe {
956-
match state {
957-
Self::REF_STORAGE => ManuallyDrop::drop(&mut data.storage_cell),
958-
Self::REF_REPLACED => ManuallyDrop::drop(&mut data.replaced_cell),
959-
_ => {}
960-
}
853+
if initialized {
854+
unsafe { ManuallyDrop::drop(&mut data.storage_cell) }
961855
}
962856
}
963857
}
@@ -967,22 +861,10 @@ unsafe impl Send for StorageCell {}
967861
unsafe impl Sync for StorageCell {}
968862

969863
pub union StorageCellReferenceData {
970-
/// Incplmete state.
864+
/// Incomplete state.
971865
hash: HashBytes,
972866
/// Complete state.
973867
storage_cell: ManuallyDrop<Arc<StorageCell>>,
974-
/// Replaced state.
975-
replaced_cell: ManuallyDrop<Cell>,
976-
}
977-
978-
impl StorageCellReferenceData {
979-
unsafe fn take_storage_cell(&mut self) -> Cell {
980-
Cell::from(ManuallyDrop::take(&mut self.storage_cell) as Arc<_>)
981-
}
982-
983-
unsafe fn take_replaced_cell(&mut self) -> Cell {
984-
ManuallyDrop::take(&mut self.replaced_cell)
985-
}
986868
}
987869

988870
struct RawCellsCache(Cache<HashBytes, RawCellsCacheItem, CellSizeEstimator, FastHasherState>);

0 commit comments

Comments
 (0)