Skip to content
Snippets Groups Projects
Commit bf60803b authored by Hai Dang's avatar Hai Dang
Browse files

Try to separate visit map out with HashSet of raw const pointers

parent 098069ec
No related tags found
No related merge requests found
...@@ -6,11 +6,11 @@ mod ghost { ...@@ -6,11 +6,11 @@ mod ghost {
use ghostcell::dfs_arena::*; use ghostcell::dfs_arena::*;
use typed_arena::Arena as TypedArena; use typed_arena::Arena as TypedArena;
pub fn init<'arena, 'mark, 'id>( pub fn init<'arena, 'id>(
arena : &'arena TypedArena<Node<'arena, 'mark, 'id, u32>>, arena : &'arena TypedArena<Node<'arena, 'id, u32>>,
token : &mut GhostToken<'id>, token : &mut GhostToken<'id>,
node_size : usize, node_size : usize,
) -> Graph<'arena, 'mark, 'id, u32> { ) -> (NodeRef<'arena, 'id, u32>, Vec<NodeRef<'arena, 'id, u32>>) {
let mut nodes : Vec<NodeRef<_>> = Vec::with_capacity(node_size); let mut nodes : Vec<NodeRef<_>> = Vec::with_capacity(node_size);
let edge_size = 4; let edge_size = 4;
for i in 0..node_size as u32 { for i in 0..node_size as u32 {
...@@ -37,7 +37,29 @@ mod ghost { ...@@ -37,7 +37,29 @@ mod ghost {
for i in (node_size/2+1)..(node_size) { for i in (node_size/2+1)..(node_size) {
nodes[i].borrow_mut(token).add_edge(nodes[i-node_size/2]); nodes[i].borrow_mut(token).add_edge(nodes[i-node_size/2]);
} }
Graph::new(nodes[0], nodes) (nodes[0], nodes)
}
pub fn dfs_immut<'arena, 'id>(
root: NodeRef<'arena, 'id, u32>,
node_size: usize,
token: &GhostToken<'id>,
f: impl Fn(&u32),
) {
let mut dfs = DFS::new(root, node_size);
for n in dfs.iter(token) {
f(n);
}
}
pub fn dfs_mut<'arena, 'id>(
root: NodeRef<'arena, 'id, u32>,
node_size: usize,
token: &mut GhostToken<'id>,
mut f: impl FnMut(&mut u32)
) {
let mut dfs = DFS::new(root, node_size);
dfs.iter_mut(token, f);
} }
} }
...@@ -158,28 +180,26 @@ fn bench_dfs(c: &mut Criterion) { ...@@ -158,28 +180,26 @@ fn bench_dfs(c: &mut Criterion) {
c.bench_function("dfs arena ghostcell immut", |b| { c.bench_function("dfs arena ghostcell immut", |b| {
GhostToken::new(|mut token| { GhostToken::new(|mut token| {
GhostToken::new(|mut mark| {
let arena = TypedArena::with_capacity(node_size as usize); let arena = TypedArena::with_capacity(node_size as usize);
let graph = ghost::init(&arena, &mut token, node_size); let (root, _) = ghost::init(&arena, &mut token, node_size);
b.iter(|| { b.iter(|| {
black_box(graph.dfs_immut(&token, &mut mark, node_size/2, |n| { black_box(ghost::dfs_immut(root, node_size, &token, |n| {
black_box(n); black_box(n);
})) }))
}) })
})}); });
}); });
c.bench_function("dfs arena ghostcell mut", |b| { c.bench_function("dfs arena ghostcell mut", |b| {
GhostToken::new(|mut token| { GhostToken::new(|mut token| {
GhostToken::new(|mut mark| {
let arena = TypedArena::with_capacity(node_size as usize); let arena = TypedArena::with_capacity(node_size as usize);
let graph = ghost::init(&arena, &mut token, node_size); let (root, _) = ghost::init(&arena, &mut token, node_size);
b.iter(|| { b.iter(|| {
black_box(graph.dfs_mut(&mut token, &mut mark, node_size/2, |n| { black_box(ghost::dfs_mut(root, node_size, &mut token, |n| {
black_box(n); black_box(n);
})) }))
}) })
})}); });
}); });
......
...@@ -2,12 +2,12 @@ use ghostcell::GhostToken; ...@@ -2,12 +2,12 @@ use ghostcell::GhostToken;
use ghostcell::dfs_arena::*; use ghostcell::dfs_arena::*;
use typed_arena::Arena as TypedArena; use typed_arena::Arena as TypedArena;
pub fn init<'arena, 'mark, 'id>( pub fn init<'arena, 'id>(
arena : &'arena TypedArena<Node<'arena, 'mark, 'id, u32>>, arena : &'arena TypedArena<Node<'arena, 'id, u32>>,
token : &mut GhostToken<'id>, token : &mut GhostToken<'id>,
node_size : usize, node_size : usize,
per_node_edge_size : usize, per_node_edge_size : usize,
) -> Graph<'arena, 'mark, 'id, u32> { ) -> (NodeRef<'arena, 'id, u32>, Vec<NodeRef<'arena, 'id, u32>>) {
let mut nodes : Vec<NodeRef<_>> = Vec::with_capacity(node_size); let mut nodes : Vec<NodeRef<_>> = Vec::with_capacity(node_size);
for i in 0..node_size as u32 { for i in 0..node_size as u32 {
nodes.push(Node::with_capacity(i, per_node_edge_size, arena)); nodes.push(Node::with_capacity(i, per_node_edge_size, arena));
...@@ -28,22 +28,30 @@ pub fn init<'arena, 'mark, 'id>( ...@@ -28,22 +28,30 @@ pub fn init<'arena, 'mark, 'id>(
for i in 0..(node_size/2-1) { for i in 0..(node_size/2-1) {
nodes[i+node_size/2].borrow_mut(token).add_edge(nodes[i+1]); nodes[i+node_size/2].borrow_mut(token).add_edge(nodes[i+1]);
} }
Graph::new(nodes[0], nodes)
(nodes[0], nodes)
} }
fn main() { fn main() {
let node_size = 10; let node_size = 10;
let per_node_edge_size = 5; let per_node_edge_size = 5;
GhostToken::new(|mut token| { GhostToken::new(|mut token| {
GhostToken::new(|mut mark| {
let arena = TypedArena::with_capacity(node_size as usize); let arena = TypedArena::with_capacity(node_size as usize);
let graph = init(&arena, &mut token, node_size, per_node_edge_size); let (root, _nodes) = init(&arena, &mut token, node_size, per_node_edge_size);
graph.dfs_immut(&token, &mut mark, node_size, |n| { print!(" {}", n) });
let mut visitor = DFS::new(root, node_size);
for n in visitor.iter(&token) {
print!(" {}", n);
}
println!(); println!();
graph.reset_mark(&token, &mut mark);
graph.dfs_mut(&mut token, &mut mark, node_size, |n| { *n *= 10 }); visitor.reset(root);
graph.reset_mark(&token, &mut mark); visitor.iter_mut(&mut token, |n| { *n *= 10 });
graph.dfs_immut(&token, &mut mark, node_size, |n| { print!(" {}", n) });
visitor.reset(root);
for n in visitor.iter(&token) {
print!(" {}", n);
}
println!(); println!();
})}); });
} }
...@@ -2,33 +2,26 @@ ...@@ -2,33 +2,26 @@
use crate::{GhostCell, GhostToken}; use crate::{GhostCell, GhostToken};
use typed_arena::Arena as TypedArena; use typed_arena::Arena as TypedArena;
use std::collections::HashSet;
/// A graph node with a marker field. /// A graph node with a marker field.
pub struct Node<'arena, 'mark, 'id, T> { pub struct Node<'arena, 'id, T> {
data : T, data : T,
mark : GhostCell<'mark, bool>, edges : Vec<NodeRef<'arena, 'id, T>>,
edges : Vec<NodeRef<'arena, 'mark, 'id, T>>,
} }
/// A reference to a node. /// A reference to a node.
pub type NodeRef<'arena, 'mark, 'id, T> = &'arena GhostCell<'id, Node<'arena, 'mark, 'id, T>>; pub type NodeRef<'arena, 'id, T> = &'arena GhostCell<'id, Node<'arena, 'id, T>>;
/// A graph with a root. Internally has a vector to keep track of all nodes in the graph. impl<'arena, 'id, T> Node<'arena, 'id, T> {
pub struct Graph<'arena, 'mark, 'id, T> {
root : NodeRef<'arena, 'mark, 'id, T>,
nodes : Vec<NodeRef<'arena, 'mark, 'id, T>>,
}
impl<'arena, 'mark, 'id, T> Node<'arena, 'mark, 'id, T> {
/// Create a new isolated node from T. Requires an arena. /// Create a new isolated node from T. Requires an arena.
pub fn new( pub fn new(
data : T, data : T,
arena : &'arena TypedArena<Node<'arena, 'mark, 'id, T>> arena : &'arena TypedArena<Node<'arena, 'id, T>>
) -> NodeRef<'arena, 'mark, 'id, T> { ) -> NodeRef<'arena, 'id, T> {
GhostCell::from_mut(arena.alloc( GhostCell::from_mut(arena.alloc(
Self { Self {
data, data,
mark: GhostCell::new(false),
edges: vec![], edges: vec![],
} }
)) ))
...@@ -37,92 +30,103 @@ impl<'arena, 'mark, 'id, T> Node<'arena, 'mark, 'id, T> { ...@@ -37,92 +30,103 @@ impl<'arena, 'mark, 'id, T> Node<'arena, 'mark, 'id, T> {
pub fn with_capacity( pub fn with_capacity(
data: T, data: T,
edge_size : usize, edge_size : usize,
arena : &'arena TypedArena<Node<'arena, 'mark, 'id, T>> arena : &'arena TypedArena<Node<'arena, 'id, T>>
) -> NodeRef<'arena, 'mark, 'id, T> { ) -> NodeRef<'arena, 'id, T> {
GhostCell::from_mut(arena.alloc( GhostCell::from_mut(arena.alloc(
Self { Self {
data, data,
mark: GhostCell::new(false),
edges: Vec::with_capacity(edge_size), edges: Vec::with_capacity(edge_size),
} }
)) ))
} }
pub fn add_edge(&mut self, child : NodeRef<'arena, 'mark, 'id, T>) { pub fn add_edge(&mut self, child : NodeRef<'arena, 'id, T>) {
self.edges.push(child) self.edges.push(child)
} }
} }
impl<'arena, 'mark, 'id, T> Graph<'arena, 'mark, 'id, T> { /// A DFS traversal structure that stores a visit map.
/// We use a HashSet of raw pointers to track the visited node, but we never
/// deference those---we only deference references stored in the stack.
pub struct DFS<'arena, 'id, T>{
stack: Vec<NodeRef<'arena, 'id, T>>,
mark: HashSet<*const GhostCell<'id, Node<'arena, 'id, T>>>
}
impl<'arena, 'id, T> DFS<'arena, 'id, T> {
pub fn new( pub fn new(
root : NodeRef<'arena, 'mark, 'id, T>, node: NodeRef<'arena, 'id, T>,
nodes : Vec<NodeRef<'arena, 'mark, 'id, T>> node_size: usize, // used to pre-empt the stack and set size
) -> Self { ) -> Self {
let mut stack = Vec::with_capacity(node_size/2);
stack.push(node);
Self { Self {
root : root, stack: stack,
nodes : nodes, mark: HashSet::with_capacity(node_size),
} }
} }
pub fn reset_mark( pub fn reset(&mut self, node: NodeRef<'arena, 'id, T>) {
&self, self.stack.clear();
token : &GhostToken<'id>, self.stack.push(node);
mark : &mut GhostToken<'mark>) { self.mark.clear();
for node in self.nodes.iter() { }
*node.borrow(token).mark.borrow_mut(mark) = false;
pub fn iter<'iter>(
&'iter mut self,
token: &'iter GhostToken<'id>
) -> DFSIter<'arena, 'id, 'iter, T> {
DFSIter {
_inner: self,
token: token
} }
} }
pub fn dfs_immut( pub fn iter_mut(
&self, &mut self,
token : &GhostToken<'id>, token : &mut GhostToken<'id>,
mark : &mut GhostToken<'mark>, mut f: impl FnMut(&mut T),
node_size : usize, // used to pre-empt the stack size
f: impl Fn(&T),
) { ) {
let mut stack : Vec<NodeRef<_>> = Vec::with_capacity(node_size/2); while let Some(node) = self.stack.pop() {
if !self.mark.contains(&(node as *const _)) {
stack.push(self.root); self.mark.insert(node);
while let Some(node) = stack.pop() { let node = node.borrow_mut(token);
let node = node.borrow(token); f(&mut node.data);
let marked = node.mark.borrow_mut(mark); for child in node.edges.iter().rev() {
if *marked == false { if !self.mark.contains(&(*child as *const _)) {
*marked = true; self.stack.push(child)
f(&node.data); }
}
for child in node.edges.iter().rev() {
let marked = child.borrow(token).mark.borrow(mark);
if *marked == false {
stack.push(child)
} }
} }
} }
} }
}
pub fn dfs_mut( pub struct DFSIter<'arena, 'id, 'iter, T> {
&self, _inner: &'iter mut DFS<'arena, 'id, T>,
token : &mut GhostToken<'id>, token: &'iter GhostToken<'id>,
mark : &mut GhostToken<'mark>, }
node_size : usize, // used to pre-empt the stack size
mut f: impl FnMut(&mut T),
) {
let mut stack : Vec<NodeRef<_>> = Vec::with_capacity(node_size/2);
stack.push(self.root); impl<'arena, 'id, 'iter, T> Iterator for DFSIter<'arena, 'id, 'iter, T>
while let Some(node) = stack.pop() { where
let node_mut = node.borrow_mut(token); T: 'iter,
let marked = node_mut.mark.borrow_mut(mark); 'arena: 'iter,
if *marked == false { {
*marked = true; type Item = &'iter T;
f(&mut node_mut.data);
} fn next(&mut self) -> Option<Self::Item> {
let node = node.borrow(token); while let Some(node) = self._inner.stack.pop() {
for child in node.edges.iter().rev() { if !self._inner.mark.contains(&(node as *const _)) {
let marked = child.borrow(token).mark.borrow(mark); self._inner.mark.insert(node);
if *marked == false { let node = node.borrow(self.token);
stack.push(child) for child in node.edges.iter().rev() {
if !self._inner.mark.contains(&(*child as *const _)) {
self._inner.stack.push(child)
}
} }
return Some(&node.data)
} }
} }
None
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment