mirror of
https://github.com/lisk77/comet.git
synced 2025-10-23 21:38:50 +00:00
feat: added pagination to the SparseSet
to make it more memory efficient
This commit is contained in:
parent
a42ac5b8fd
commit
ca3c3dd5e6
3 changed files with 57 additions and 29 deletions
|
@ -5,7 +5,6 @@ use std::{
|
|||
},
|
||||
any::TypeId,
|
||||
hash::{
|
||||
DefaultHasher,
|
||||
Hash,
|
||||
Hasher
|
||||
},
|
||||
|
@ -14,6 +13,9 @@ use std::{
|
|||
};
|
||||
use std::ptr;
|
||||
|
||||
// The following two structs are just blatantly stolen from Bevy - another Rust game engine.
|
||||
// I just need them for the ComponentStorage system, and I was too lazy to write them myself.
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BlobVec {
|
||||
item_layout: Layout,
|
||||
|
@ -24,7 +26,6 @@ pub struct BlobVec {
|
|||
drop: unsafe fn(*mut u8)
|
||||
}
|
||||
|
||||
|
||||
impl BlobVec {
|
||||
pub fn new(item_layout: Layout, drop: unsafe fn(*mut u8), capacity: usize) -> Self {
|
||||
if item_layout.size() == 0 {
|
||||
|
@ -84,7 +85,6 @@ impl BlobVec {
|
|||
self.capacity = new_capacity;
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
|
|
|
@ -8,7 +8,7 @@ impl ComponentStorage {
|
|||
|
||||
pub fn register_component<T: 'static>(&mut self, capacity: usize) {
|
||||
if !self.contains(&TypeId::of::<T>()) {
|
||||
self.insert(TypeId::of::<T>(), SparseSet::new::<T>(capacity));
|
||||
self.insert(TypeId::of::<T>(), SparseSet::new::<T>(capacity, 1000));
|
||||
}
|
||||
else {
|
||||
error!("Component {:?} already exists", TypeId::of::<T>());
|
||||
|
|
|
@ -5,55 +5,83 @@ use std::hash::{
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SparseSet {
|
||||
sparse: Vec<Option<usize>>,
|
||||
sparse: Vec<Option<Vec<Option<usize>>>>,
|
||||
dense: Column,
|
||||
page_size: usize
|
||||
}
|
||||
|
||||
impl SparseSet {
|
||||
pub fn new<T: 'static>(capacity: usize) -> Self {
|
||||
pub fn new<T: 'static>(capacity: usize, page_size: usize) -> Self {
|
||||
Self {
|
||||
sparse: Vec::new(),
|
||||
dense: Column::new::<T>(capacity),
|
||||
page_size
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert<T: 'static>(&mut self, index: usize, value: T) {
|
||||
if index >= self.sparse.len() {
|
||||
self.sparse.resize(index + 1, None);
|
||||
let page = index / self.page_size;
|
||||
|
||||
if page >= self.sparse.len() {
|
||||
self.sparse.resize(page + 1, None);
|
||||
}
|
||||
self.sparse[index] = Some(self.dense.data.len());
|
||||
|
||||
if self.sparse[page].is_none() {
|
||||
self.sparse[page] = Some(vec![None; self.page_size]);
|
||||
}
|
||||
|
||||
if let Some(page_vec) = &mut self.sparse[page] {
|
||||
page_vec[index % self.page_size] = Some(self.dense.data.len());
|
||||
}
|
||||
|
||||
self.dense.push(value);
|
||||
}
|
||||
|
||||
pub fn remove<T: 'static>(&mut self, index: usize) -> Option<T>{
|
||||
if let Some(sparse_index) = self.sparse.get(index).and_then(|x| x.as_ref()) {
|
||||
let dense_index = *sparse_index;
|
||||
let last_index = self.dense.data.len() - 1;
|
||||
if dense_index != last_index {
|
||||
self.dense.swap(dense_index, last_index);
|
||||
if let Some(sparse) = self.sparse.get_mut(last_index) {
|
||||
*sparse = Some(dense_index);
|
||||
pub fn remove<T: 'static>(&mut self, index: usize) -> Option<T> {
|
||||
if let Some(page_vec) = self.sparse.get(index / self.page_size).and_then(|x| x.as_ref()) {
|
||||
if let Some(sparse_index) = page_vec.get(index % self.page_size).and_then(|x| x.as_ref()) {
|
||||
let dense_index = *sparse_index;
|
||||
let last_index = self.dense.data.len() - 1;
|
||||
if dense_index != last_index {
|
||||
self.dense.swap(dense_index, last_index);
|
||||
if let Some(page_vec) = self.sparse.get_mut(last_index / self.page_size).and_then(|x| x.as_mut()) {
|
||||
page_vec[last_index % self.page_size] = Some(dense_index);
|
||||
}
|
||||
}
|
||||
if let Some(page_vec) = self.sparse.get_mut(index / self.page_size).and_then(|x| x.as_mut()) {
|
||||
page_vec[index % self.page_size] = None;
|
||||
}
|
||||
return self.dense.remove::<T>(last_index);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get<T: 'static>(&self, index: usize) -> Option<&T> {
|
||||
if let Some(page_vec) = self.sparse.get(index / self.page_size).and_then(|x| x.as_ref()) {
|
||||
if let Some(sparse_index) = page_vec.get(index % self.page_size).and_then(|x| x.as_ref()) {
|
||||
self.dense.get::<T>(*sparse_index)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
self.sparse[index] = None;
|
||||
self.dense.remove::<T>(last_index)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get<T: 'static>(&self, index: usize) -> Option<&T> {
|
||||
match self.sparse.get(index).and_then(|x| x.as_ref()) {
|
||||
Some(sparse_index) => self.dense.get::<T>(*sparse_index),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut<T: 'static>(&mut self, index: usize) -> Option<&mut T> {
|
||||
match self.sparse.get(index).and_then(|x| x.as_ref()) {
|
||||
Some(sparse_index) => self.dense.get_mut::<T>(*sparse_index),
|
||||
None => None,
|
||||
if let Some(page_vec) = self.sparse.get(index / self.page_size).and_then(|x| x.as_ref()) {
|
||||
if let Some(sparse_index) = page_vec.get(index % self.page_size).and_then(|x| x.as_ref()) {
|
||||
self.dense.get_mut::<T>(*sparse_index)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue