Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
G
ghostcell
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
FP
ghostcell
Commits
bf60803b
Commit
bf60803b
authored
4 years ago
by
Hai Dang
Browse files
Options
Downloads
Patches
Plain Diff
Try to separate visit map out with HashSet of raw const pointers
parent
098069ec
Branches
hai/hashset_raw_pointer
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
ghostcell/benches/dfs.rs
+32
-12
32 additions, 12 deletions
ghostcell/benches/dfs.rs
ghostcell/examples/dfs_arena.rs
+20
-12
20 additions, 12 deletions
ghostcell/examples/dfs_arena.rs
ghostcell/src/dfs_arena.rs
+74
-70
74 additions, 70 deletions
ghostcell/src/dfs_arena.rs
with
126 additions
and
94 deletions
ghostcell/benches/dfs.rs
+
32
−
12
View file @
bf60803b
...
@@ -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
(
g
raph
.
dfs_immut
(
&
token
,
&
mut
mark
,
node_size
/
2
,
|
n
|
{
black_box
(
g
host
::
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
(
g
raph
.
dfs_mut
(
&
mut
token
,
&
mut
mark
,
node_size
/
2
,
|
n
|
{
black_box
(
g
host
::
dfs_mut
(
root
,
node_size
,
&
mut
token
,
|
n
|
{
black_box
(
n
);
black_box
(
n
);
}))
}))
})
})
})
});
});
});
});
...
...
This diff is collapsed.
Click to expand it.
ghostcell/examples/dfs_arena.rs
+
20
−
12
View file @
bf60803b
...
@@ -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!
();
})
});
});
}
}
This diff is collapsed.
Click to expand it.
ghostcell/src/dfs_arena.rs
+
74
−
70
View file @
bf60803b
...
@@ -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
>
,
node
s
:
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
}
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment