From 9ba980d9d844bee9dc02f2cc4a90e6e7a78bc179 Mon Sep 17 00:00:00 2001 From: squi.dev Date: Mon, 10 Aug 2026 11:34:05 +0000 Subject: [PATCH] perf stuf --- src/entity.rs | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------- 1 file(s) changed, 65 insertion(s)(+), 55 deletion(s)(-) diff --git a/src/entity.rs b/src/entity.rs --- a/src/entity.rs +++ b/src/entity.rs @@ -1,100 +1,109 @@ -use core::num::NonZero; - -use alloc::collections::vec_deque::VecDeque; use alloc::vec; use alloc::vec::Vec; +use core::num::NonZero; #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Entity(pub(crate) u32, pub(crate) NonZero); pub struct Census { - storage: Vec>, - masks: VecDeque, - mask_offset: u32, + storage: Vec>>, + masks: Vec, + lowest_open: usize, } impl Census { pub fn new() -> Self { Census { storage: vec![], - masks: VecDeque::new(), - mask_offset: 0, + masks: vec![], + lowest_open: 0, } } #[inline(always)] - fn inc(&mut self, idx: u32) -> NonZero { - let new = self.storage[idx as usize].saturating_add(1); - self.storage[idx as usize] = new; - new + unsafe fn inc(&mut self, idx: u32) -> NonZero { + let n = match unsafe { self.storage.get_unchecked(idx as usize) } { + Some(n) => n.saturating_add(1), + None => NonZero::new(1).unwrap(), + }; + self.storage[idx as usize] = Some(n); + n } #[inline(always)] - fn mark_used(&mut self, idx: u32) { - let real = idx - self.mask_offset; - let mask_idx = (real / u64::BITS) as usize; - let mask_pos = (real % u64::BITS) as u64; - - self.masks[mask_idx] ^= 1u64 << mask_pos; - if self.masks[0] == 0 { - self.masks.pop_front(); - self.mask_offset += u64::BITS; + unsafe fn mark_empty(&mut self, idx: u32) { + let mask_idx = (idx / u64::BITS) as usize; + let mask_pos = (idx % u64::BITS) as u64; + unsafe { + *self.masks.get_unchecked_mut(mask_idx) |= 1u64 << mask_pos; } - } - - #[inline(always)] - fn mark_empty(&mut self, idx: u32) { - let real = idx - self.mask_offset; - let mask_idx = (real / u64::BITS) as usize; - let mask_pos = (real % u64::BITS) as u64; - - self.masks[mask_idx] |= 1u64 << mask_pos; + self.lowest_open = self.lowest_open.min(mask_idx); } #[inline(always)] pub fn reserve(&mut self) -> Entity { - for mask in self.masks.iter().filter(|m| **m != 0) { + for (n, mask) in self + .masks + .iter() + .enumerate() + .skip(self.lowest_open) + .filter(|(_, m)| **m != 0) + { if let Some(mask_idx) = mask.lowest_one() { - let idx = mask_idx + self.mask_offset; - self.mark_used(idx); - return Entity(idx, self.inc(idx)); + let idx = mask_idx + n as u32 * u64::BITS; + self.lowest_open = self.lowest_open.max(n); + // SAFTEY: idx/n come from iterator, must be smaller then storage + unsafe { + *(self.masks.get_unchecked_mut(n)) -= 1u64 << mask_idx; + return Entity(idx, self.inc(idx)); + } + } else { + unreachable!(); } } let one = NonZero::new(1).unwrap(); let idx = self.storage.len() as u32; - - self.storage.extend((0..64).map(|_| one)); - self.masks.push_back(u64::MAX - 1); + self.storage.push(Some(one)); + self.storage.extend((0..63).map(|_| None)); + self.masks.push(u64::MAX - 1); + self.lowest_open = self.masks.len() - 1; Entity(idx, one) } #[inline(always)] pub fn remove(&mut self, Entity(idx, _): Entity) { - if idx < self.mask_offset { - while self.mask_offset > idx { - self.masks.push_front(0); - self.mask_offset -= u64::BITS; - } + if idx as usize >= self.storage.len() { + core::hint::cold_path(); + return; + } + + // SAFETY: idx is smaller then size of storage + unsafe { + self.mark_empty(idx); } - self.mark_empty(idx); } #[inline(always)] pub fn validate(&self, Entity(idx, generation): Entity) -> bool { - (self.storage[idx as usize] == generation) && self.is_taken(idx) + if idx as usize >= self.storage.len() { + core::hint::cold_path(); + return false; + } + unsafe { + self.is_taken(idx) + && (self + .storage + .get_unchecked(idx as usize) + .is_some_and(|g| g == generation)) + } } #[inline(always)] - fn is_taken(&self, idx: u32) -> bool { - if idx < self.mask_offset { - return true; - } - let real = idx - self.mask_offset; - let mask_idx = (real / u64::BITS) as usize; - let mask_pos = (real % u64::BITS) as u64; - - (self.masks[mask_idx] & 1u64 << mask_pos) == 0 + unsafe fn is_taken(&self, idx: u32) -> bool { + let mask_idx = (idx / u64::BITS) as usize; + let mask_pos = (idx % u64::BITS) as u64; + unsafe { (*self.masks.get_unchecked(mask_idx) & 1u64 << mask_pos) == 0 } } } @@ -153,19 +162,20 @@ let e1 = cen.reserve(); let e2 = cen.reserve(); assert_ne!(e1, e2); + assert_ne!(e1.0, e2.0); } #[test] fn many() { let mut cen = Census::new(); let first = cen.reserve(); - for _ in 0..129 { + for _ in 0..128 { cen.reserve(); } let last = cen.reserve(); assert_ne!(last, first); - assert_eq!(last.0, 130); + assert_eq!(last.0, 129); } #[test] -- tangled.sh