Arena allocate vertices

This reduces the instruction count by 4% on larger files, such as
slow_before/after.rs.

Co-authored-by: mgt <mgt@oi-wiki.org>
pull/290/head
Wilfred Hughes 2022-05-21 22:12:43 +07:00
parent f7aa78bd2b
commit 1646d456f4
2 changed files with 37 additions and 34 deletions

@ -11,20 +11,22 @@ use crate::{
use itertools::Itertools; use itertools::Itertools;
use radix_heap::RadixHeapMap; use radix_heap::RadixHeapMap;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use typed_arena::Arena;
type PredecessorInfo<'a> = (u64, Rc<Vertex<'a>>, Edge); type PredecessorInfo<'a, 'b> = (u64, &'b Vertex<'a>, Edge);
fn shortest_path(start: Vertex) -> Vec<(Edge, Rc<Vertex>)> { fn shortest_path(start: Vertex) -> Vec<(Edge, Vertex)> {
// We want to visit nodes with the shortest distance first, but // We want to visit nodes with the shortest distance first, but
// RadixHeapMap is a max-heap. Ensure nodes are wrapped with // RadixHeapMap is a max-heap. Ensure nodes are wrapped with
// Reverse to flip comparisons. // Reverse to flip comparisons.
let mut heap: RadixHeapMap<Reverse<_>, Rc<Vertex>> = RadixHeapMap::new(); let mut heap: RadixHeapMap<Reverse<_>, &Vertex> = RadixHeapMap::new();
heap.push(Reverse(0), Rc::new(start)); let vertex_arena: Arena<Vertex> = Arena::new();
heap.push(Reverse(0), vertex_arena.alloc(start));
// TODO: this grows very big. Consider using IDA* to reduce memory // TODO: this grows very big. Consider using IDA* to reduce memory
// usage. // usage.
let mut predecessors: FxHashMap<Rc<Vertex>, PredecessorInfo> = FxHashMap::default(); let mut predecessors: FxHashMap<&Vertex, PredecessorInfo> = FxHashMap::default();
let mut neighbour_buf = [ let mut neighbour_buf = [
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
@ -36,7 +38,7 @@ fn shortest_path(start: Vertex) -> Vec<(Edge, Rc<Vertex>)> {
break current; break current;
} }
neighbours(&current, &mut neighbour_buf); neighbours(current, &mut neighbour_buf, &vertex_arena);
for neighbour in &mut neighbour_buf { for neighbour in &mut neighbour_buf {
if let Some((edge, next)) = neighbour.take() { if let Some((edge, next)) = neighbour.take() {
let distance_to_next = distance + edge.cost(); let distance_to_next = distance + edge.cost();
@ -46,10 +48,7 @@ fn shortest_path(start: Vertex) -> Vec<(Edge, Rc<Vertex>)> {
}; };
if found_shorter_route { if found_shorter_route {
let next = Rc::new(next); predecessors.insert(next, (distance_to_next, current, edge));
predecessors
.insert(next.clone(), (distance_to_next, current.clone(), edge));
heap.push(Reverse(distance_to_next), next); heap.push(Reverse(distance_to_next), next);
} }
@ -69,7 +68,7 @@ fn shortest_path(start: Vertex) -> Vec<(Edge, Rc<Vertex>)> {
); );
let mut current = end; let mut current = end;
let mut route: Vec<(Edge, Rc<Vertex>)> = vec![]; let mut route: Vec<(Edge, Vertex)> = vec![];
let mut cost = 0; let mut cost = 0;
while let Some((_, node, edge)) = predecessors.remove(&current) { while let Some((_, node, edge)) = predecessors.remove(&current) {
route.push((edge, node.clone())); route.push((edge, node.clone()));

@ -5,9 +5,9 @@ use std::{
cmp::min, cmp::min,
fmt, fmt,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
rc::Rc,
}; };
use strsim::normalized_levenshtein; use strsim::normalized_levenshtein;
use typed_arena::Arena;
use crate::{ use crate::{
changes::{insert_deep_unchanged, ChangeKind, ChangeMap}, changes::{insert_deep_unchanged, ChangeKind, ChangeMap},
@ -332,7 +332,11 @@ impl Edge {
} }
/// Calculate all the neighbours from `v` and write them to `buf`. /// Calculate all the neighbours from `v` and write them to `buf`.
pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) { pub fn neighbours<'a, 'b>(
v: &Vertex<'a>,
buf: &mut [Option<(Edge, &'b Vertex<'a>)>],
alloc: &'b Arena<Vertex<'a>>,
) {
for item in &mut *buf { for item in &mut *buf {
*item = None; *item = None;
} }
@ -347,14 +351,14 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
// Continue from sibling of parent. // Continue from sibling of parent.
buf[i] = Some(( buf[i] = Some((
ExitDelimiterBoth, ExitDelimiterBoth,
Vertex { alloc.alloc(Vertex {
lhs_syntax: lhs_parent.next_sibling(), lhs_syntax: lhs_parent.next_sibling(),
rhs_syntax: rhs_parent.next_sibling(), rhs_syntax: rhs_parent.next_sibling(),
can_pop_either: can_pop_either_parent(&parents_next), can_pop_either: can_pop_either_parent(&parents_next),
parents: parents_next, parents: parents_next,
lhs_parent_id: lhs_parent.parent().map(Syntax::id), lhs_parent_id: lhs_parent.parent().map(Syntax::id),
rhs_parent_id: rhs_parent.parent().map(Syntax::id), rhs_parent_id: rhs_parent.parent().map(Syntax::id),
}, }),
)); ));
i += 1; i += 1;
} }
@ -367,14 +371,14 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
// Continue from sibling of parent. // Continue from sibling of parent.
buf[i] = Some(( buf[i] = Some((
ExitDelimiterLHS, ExitDelimiterLHS,
Vertex { alloc.alloc(Vertex {
lhs_syntax: lhs_parent.next_sibling(), lhs_syntax: lhs_parent.next_sibling(),
rhs_syntax: v.rhs_syntax, rhs_syntax: v.rhs_syntax,
can_pop_either: can_pop_either_parent(&parents_next), can_pop_either: can_pop_either_parent(&parents_next),
parents: parents_next, parents: parents_next,
lhs_parent_id: lhs_parent.parent().map(Syntax::id), lhs_parent_id: lhs_parent.parent().map(Syntax::id),
rhs_parent_id: v.rhs_parent_id, rhs_parent_id: v.rhs_parent_id,
}, }),
)); ));
i += 1; i += 1;
} }
@ -387,14 +391,14 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
// Continue from sibling of parent. // Continue from sibling of parent.
buf[i] = Some(( buf[i] = Some((
ExitDelimiterRHS, ExitDelimiterRHS,
Vertex { alloc.alloc(Vertex {
lhs_syntax: v.lhs_syntax, lhs_syntax: v.lhs_syntax,
rhs_syntax: rhs_parent.next_sibling(), rhs_syntax: rhs_parent.next_sibling(),
can_pop_either: can_pop_either_parent(&parents_next), can_pop_either: can_pop_either_parent(&parents_next),
parents: parents_next, parents: parents_next,
lhs_parent_id: v.lhs_parent_id, lhs_parent_id: v.lhs_parent_id,
rhs_parent_id: rhs_parent.parent().map(Syntax::id), rhs_parent_id: rhs_parent.parent().map(Syntax::id),
}, }),
)); ));
i += 1; i += 1;
} }
@ -409,14 +413,14 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
// Both nodes are equal, the happy case. // Both nodes are equal, the happy case.
buf[i] = Some(( buf[i] = Some((
UnchangedNode { depth_difference }, UnchangedNode { depth_difference },
Vertex { alloc.alloc(Vertex {
lhs_syntax: lhs_syntax.next_sibling(), lhs_syntax: lhs_syntax.next_sibling(),
rhs_syntax: rhs_syntax.next_sibling(), rhs_syntax: rhs_syntax.next_sibling(),
parents: v.parents.clone(), parents: v.parents.clone(),
lhs_parent_id: v.lhs_parent_id, lhs_parent_id: v.lhs_parent_id,
rhs_parent_id: v.rhs_parent_id, rhs_parent_id: v.rhs_parent_id,
can_pop_either: v.can_pop_either, can_pop_either: v.can_pop_either,
}, }),
)); ));
i += 1; i += 1;
} }
@ -450,14 +454,14 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
buf[i] = Some(( buf[i] = Some((
EnterUnchangedDelimiter { depth_difference }, EnterUnchangedDelimiter { depth_difference },
Vertex { alloc.alloc(Vertex {
lhs_syntax: lhs_next, lhs_syntax: lhs_next,
rhs_syntax: rhs_next, rhs_syntax: rhs_next,
parents: parents_next, parents: parents_next,
lhs_parent_id: Some(lhs_syntax.id()), lhs_parent_id: Some(lhs_syntax.id()),
rhs_parent_id: Some(rhs_syntax.id()), rhs_parent_id: Some(rhs_syntax.id()),
can_pop_either: false, can_pop_either: false,
}, }),
)); ));
i += 1; i += 1;
} }
@ -483,14 +487,14 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
(normalized_levenshtein(lhs_content, rhs_content) * 100.0).round() as u8; (normalized_levenshtein(lhs_content, rhs_content) * 100.0).round() as u8;
buf[i] = Some(( buf[i] = Some((
ReplacedComment { levenshtein_pct }, ReplacedComment { levenshtein_pct },
Vertex { alloc.alloc(Vertex {
lhs_syntax: lhs_syntax.next_sibling(), lhs_syntax: lhs_syntax.next_sibling(),
rhs_syntax: rhs_syntax.next_sibling(), rhs_syntax: rhs_syntax.next_sibling(),
parents: v.parents.clone(), parents: v.parents.clone(),
lhs_parent_id: v.lhs_parent_id, lhs_parent_id: v.lhs_parent_id,
rhs_parent_id: v.rhs_parent_id, rhs_parent_id: v.rhs_parent_id,
can_pop_either: v.can_pop_either, can_pop_either: v.can_pop_either,
}, }),
)); ));
i += 1; i += 1;
} }
@ -507,14 +511,14 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
// node rather than a sibling? // node rather than a sibling?
contiguous: lhs_syntax.prev_is_contiguous(), contiguous: lhs_syntax.prev_is_contiguous(),
}, },
Vertex { alloc.alloc(Vertex {
lhs_syntax: lhs_syntax.next_sibling(), lhs_syntax: lhs_syntax.next_sibling(),
rhs_syntax: v.rhs_syntax, rhs_syntax: v.rhs_syntax,
parents: v.parents.clone(), parents: v.parents.clone(),
lhs_parent_id: v.lhs_parent_id, lhs_parent_id: v.lhs_parent_id,
rhs_parent_id: v.rhs_parent_id, rhs_parent_id: v.rhs_parent_id,
can_pop_either: v.can_pop_either, can_pop_either: v.can_pop_either,
}, }),
)); ));
i += 1; i += 1;
} }
@ -528,14 +532,14 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
EnterNovelDelimiterLHS { EnterNovelDelimiterLHS {
contiguous: lhs_syntax.prev_is_contiguous(), contiguous: lhs_syntax.prev_is_contiguous(),
}, },
Vertex { alloc.alloc(Vertex {
lhs_syntax: lhs_next, lhs_syntax: lhs_next,
rhs_syntax: v.rhs_syntax, rhs_syntax: v.rhs_syntax,
parents: parents_next, parents: parents_next,
lhs_parent_id: Some(lhs_syntax.id()), lhs_parent_id: Some(lhs_syntax.id()),
rhs_parent_id: v.rhs_parent_id, rhs_parent_id: v.rhs_parent_id,
can_pop_either: true, can_pop_either: true,
}, }),
)); ));
i += 1; i += 1;
} }
@ -550,14 +554,14 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
NovelAtomRHS { NovelAtomRHS {
contiguous: rhs_syntax.prev_is_contiguous(), contiguous: rhs_syntax.prev_is_contiguous(),
}, },
Vertex { alloc.alloc(Vertex {
lhs_syntax: v.lhs_syntax, lhs_syntax: v.lhs_syntax,
rhs_syntax: rhs_syntax.next_sibling(), rhs_syntax: rhs_syntax.next_sibling(),
parents: v.parents.clone(), parents: v.parents.clone(),
lhs_parent_id: v.lhs_parent_id, lhs_parent_id: v.lhs_parent_id,
rhs_parent_id: v.rhs_parent_id, rhs_parent_id: v.rhs_parent_id,
can_pop_either: v.can_pop_either, can_pop_either: v.can_pop_either,
}, }),
)); ));
i += 1; i += 1;
} }
@ -571,14 +575,14 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
EnterNovelDelimiterRHS { EnterNovelDelimiterRHS {
contiguous: rhs_syntax.prev_is_contiguous(), contiguous: rhs_syntax.prev_is_contiguous(),
}, },
Vertex { alloc.alloc(Vertex {
lhs_syntax: v.lhs_syntax, lhs_syntax: v.lhs_syntax,
rhs_syntax: rhs_next, rhs_syntax: rhs_next,
parents: parents_next, parents: parents_next,
lhs_parent_id: v.lhs_parent_id, lhs_parent_id: v.lhs_parent_id,
rhs_parent_id: Some(rhs_syntax.id()), rhs_parent_id: Some(rhs_syntax.id()),
can_pop_either: true, can_pop_either: true,
}, }),
)); ));
i += 1; i += 1;
} }
@ -590,7 +594,7 @@ pub fn neighbours<'a>(v: &Vertex<'a>, buf: &mut [Option<(Edge, Vertex<'a>)>]) {
); );
} }
pub fn populate_change_map<'a>(route: &[(Edge, Rc<Vertex<'a>>)], change_map: &mut ChangeMap<'a>) { pub fn populate_change_map<'a>(route: &[(Edge, Vertex<'a>)], change_map: &mut ChangeMap<'a>) {
for (e, v) in route { for (e, v) in route {
match e { match e {
ExitDelimiterBoth | ExitDelimiterLHS | ExitDelimiterRHS => { ExitDelimiterBoth | ExitDelimiterLHS | ExitDelimiterRHS => {