Skip to content

Commit 426ce97

Browse files
committed
Defer edge calculations
This saves 1.3% instructions and 7% peak memory usage (because the predecessors hash map has smaller size values).
1 parent 1f48149 commit 426ce97

File tree

1 file changed

+55
-11
lines changed

1 file changed

+55
-11
lines changed

src/diff/dijkstra.rs

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@ use itertools::Itertools;
1313
use radix_heap::RadixHeapMap;
1414
use rustc_hash::FxHashMap;
1515

16-
type PredecessorInfo<'a, 'b> = (u64, &'b Vertex<'a>, Edge);
16+
type PredecessorInfo<'a, 'b> = (u64, &'b Vertex<'a>);
1717

18-
fn shortest_path(start: Vertex, size_hint: usize) -> Vec<(Edge, Vertex)> {
18+
/// Return the shortest route from `start` to the end vertex.
19+
fn shortest_vertex_path(start: Vertex, size_hint: usize) -> Vec<Vertex> {
1920
// We want to visit nodes with the shortest distance first, but
2021
// RadixHeapMap is a max-heap. Ensure nodes are wrapped with
2122
// Reverse to flip comparisons.
2223
let mut heap: RadixHeapMap<Reverse<_>, &Vertex> = RadixHeapMap::new();
2324

2425
let vertex_arena = Bump::new();
25-
heap.push(Reverse(0), vertex_arena.alloc(start));
26+
heap.push(Reverse(0), vertex_arena.alloc(start.clone()));
2627

2728
// TODO: this grows very big. Consider using IDA* to reduce memory
2829
// usage.
@@ -44,12 +45,12 @@ fn shortest_path(start: Vertex, size_hint: usize) -> Vec<(Edge, Vertex)> {
4445
if let Some((edge, next)) = neighbour.take() {
4546
let distance_to_next = distance + edge.cost();
4647
let found_shorter_route = match predecessors.get(&next) {
47-
Some((prev_shortest, _, _)) => distance_to_next < *prev_shortest,
48+
Some((prev_shortest, _)) => distance_to_next < *prev_shortest,
4849
_ => true,
4950
};
5051

5152
if found_shorter_route {
52-
predecessors.insert(next, (distance_to_next, current, edge));
53+
predecessors.insert(next, (distance_to_next, current));
5354

5455
heap.push(Reverse(distance_to_next), next);
5556
}
@@ -69,18 +70,61 @@ fn shortest_path(start: Vertex, size_hint: usize) -> Vec<(Edge, Vertex)> {
6970
);
7071
let mut current = end;
7172

72-
let mut route: Vec<(Edge, Vertex)> = vec![];
73+
let mut vertex_route: Vec<Vertex> = vec![end.clone()];
74+
while let Some((_, node)) = predecessors.remove(&current) {
75+
vertex_route.push(node.clone());
76+
current = node;
77+
}
78+
79+
vertex_route.reverse();
80+
vertex_route
81+
}
82+
83+
fn shortest_path_with_edges<'a>(route: &[Vertex<'a>]) -> Vec<(Edge, Vertex<'a>)> {
84+
let mut prev = route.first().expect("Expected non-empty route");
85+
7386
let mut cost = 0;
74-
while let Some((_, node, edge)) = predecessors.remove(&current) {
75-
route.push((edge, node.clone()));
87+
let mut res = vec![];
88+
for vertex in route.iter().skip(1) {
89+
let edge = edge_between(prev, vertex);
90+
res.push((edge, prev.clone()));
7691
cost += edge.cost();
7792

78-
current = node;
93+
prev = vertex;
7994
}
8095
debug!("Found a path of {} with cost {}.", route.len(), cost);
8196

82-
route.reverse();
83-
route
97+
res
98+
}
99+
100+
/// Return the shortest route from the `start` to the end vertex.
101+
///
102+
/// The vec returned does not return the very last vertex. This is
103+
/// necessary because a route of N vertices only has N-1 edges.
104+
fn shortest_path(start: Vertex, size_hint: usize) -> Vec<(Edge, Vertex)> {
105+
let vertex_path = shortest_vertex_path(start, size_hint);
106+
shortest_path_with_edges(&vertex_path)
107+
}
108+
109+
fn edge_between<'a>(before: &Vertex<'a>, after: &Vertex<'a>) -> Edge {
110+
let mut neighbour_buf = [
111+
None, None, None, None, None, None, None, None, None, None, None, None,
112+
];
113+
114+
let vertex_arena = Bump::new();
115+
neighbours(before, &mut neighbour_buf, &vertex_arena);
116+
for neighbour in &mut neighbour_buf {
117+
if let Some((edge, next)) = neighbour.take() {
118+
if next == after {
119+
return edge;
120+
}
121+
}
122+
}
123+
124+
panic!(
125+
"Expected a route between the two vertices {:#?} and {:#?}",
126+
before, after
127+
);
84128
}
85129

86130
/// What is the total number of AST nodes?

0 commit comments

Comments
 (0)