Skip to content

Commit 80f3fd3

Browse files
xunilrjJoshuaBatty
andauthored
change ConcurrentSlab to use Vec (#5838)
## Description Partially addresses #5781. This reduces the time spent retrieving items in slabs. For more details see: #5782 ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [ ] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. Co-authored-by: Joshua Batty <joshpbatty@gmail.com>
1 parent a386e7b commit 80f3fd3

File tree

1 file changed

+54
-22
lines changed

1 file changed

+54
-22
lines changed

sway-core/src/concurrent_slab.rs

+54-22
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
11
use std::{
2-
collections::HashMap,
32
fmt,
43
sync::{Arc, RwLock},
54
};
65

7-
use itertools::Itertools;
6+
#[derive(Debug, Clone)]
7+
pub struct Inner<T> {
8+
pub items: Vec<Option<Arc<T>>>,
9+
pub free_list: Vec<usize>,
10+
}
11+
12+
impl<T> Default for Inner<T> {
13+
fn default() -> Self {
14+
Self {
15+
items: Default::default(),
16+
free_list: Default::default(),
17+
}
18+
}
19+
}
820

921
#[derive(Debug)]
1022
pub(crate) struct ConcurrentSlab<T> {
11-
inner: RwLock<HashMap<usize, Arc<T>>>,
12-
last_id: Arc<RwLock<usize>>,
23+
pub inner: RwLock<Inner<T>>,
1324
}
1425

1526
impl<T> Clone for ConcurrentSlab<T>
@@ -20,7 +31,6 @@ where
2031
let inner = self.inner.read().unwrap();
2132
Self {
2233
inner: RwLock::new(inner.clone()),
23-
last_id: self.last_id.clone(),
2434
}
2535
}
2636
}
@@ -29,7 +39,6 @@ impl<T> Default for ConcurrentSlab<T> {
2939
fn default() -> Self {
3040
Self {
3141
inner: Default::default(),
32-
last_id: Default::default(),
3342
}
3443
}
3544
}
@@ -58,46 +67,69 @@ impl<T> ConcurrentSlab<T>
5867
where
5968
T: Clone,
6069
{
70+
#[allow(dead_code)]
71+
pub fn len(&self) -> usize {
72+
let inner = self.inner.read().unwrap();
73+
inner.items.len()
74+
}
75+
6176
pub fn values(&self) -> Vec<Arc<T>> {
6277
let inner = self.inner.read().unwrap();
63-
inner.values().cloned().collect_vec()
78+
inner.items.iter().filter_map(|x| x.clone()).collect()
6479
}
6580

6681
pub fn insert(&self, value: T) -> usize {
67-
let mut inner = self.inner.write().unwrap();
68-
let mut last_id = self.last_id.write().unwrap();
69-
*last_id += 1;
70-
inner.insert(*last_id, Arc::new(value));
71-
*last_id
82+
self.insert_arc(Arc::new(value))
7283
}
7384

7485
pub fn insert_arc(&self, value: Arc<T>) -> usize {
7586
let mut inner = self.inner.write().unwrap();
76-
let mut last_id = self.last_id.write().unwrap();
77-
*last_id += 1;
78-
inner.insert(*last_id, value);
79-
*last_id
87+
88+
if let Some(free) = inner.free_list.pop() {
89+
assert!(inner.items[free].is_none());
90+
inner.items[free] = Some(value);
91+
free
92+
} else {
93+
inner.items.push(Some(value));
94+
inner.items.len() - 1
95+
}
8096
}
8197

8298
pub fn replace(&self, index: usize, new_value: T) -> Option<T> {
8399
let mut inner = self.inner.write().unwrap();
84-
inner.insert(index, Arc::new(new_value));
85-
None
100+
let item = inner.items.get_mut(index)?;
101+
let old = item.replace(Arc::new(new_value))?;
102+
Arc::into_inner(old)
86103
}
87104

88105
pub fn get(&self, index: usize) -> Arc<T> {
89106
let inner = self.inner.read().unwrap();
90-
inner[&index].clone()
107+
inner.items[index]
108+
.as_ref()
109+
.expect("invalid slab index for ConcurrentSlab::get")
110+
.clone()
91111
}
92112

93113
pub fn retain(&self, predicate: impl Fn(&usize, &mut Arc<T>) -> bool) {
94114
let mut inner = self.inner.write().unwrap();
95-
inner.retain(predicate);
115+
116+
let Inner { items, free_list } = &mut *inner;
117+
for (idx, item) in items.iter_mut().enumerate() {
118+
if let Some(arc) = item {
119+
if !predicate(&idx, arc) {
120+
free_list.push(idx);
121+
item.take();
122+
}
123+
}
124+
}
96125
}
97126

98127
pub fn clear(&self) {
99128
let mut inner = self.inner.write().unwrap();
100-
inner.clear();
101-
inner.shrink_to(0);
129+
inner.items.clear();
130+
inner.items.shrink_to(0);
131+
132+
inner.free_list.clear();
133+
inner.free_list.shrink_to(0);
102134
}
103135
}

0 commit comments

Comments
 (0)