Thoughts on removing `successors` allocation
chinedufn opened this issue · comments
Hey!
I'm exploring using pathfinding
's astar
implementation.
I'm noticing that the successors
function requires you to allocate a vector.
This is probably fine for most use cases - but if you're targeting a top-performance pathfinding implementation it might be a non-starter.
Has removing this allocation been considered?
The signature for successors
is currently:
fn successors(&self) -> Vec<(Pos, usize)> {
Have it been considered to instead have fn successors(&self) -> &Vec<(Pos, usize)> {
be the signature?
Then the documentation could just show an example of using a re-usable Vec<T, usize>
. The ergonomics would be roughly identical minus the user needing to clear the vector out or something like that...
i.e. (rough sketch)
let mut successors = vec![];
astar(
start,
|p| {
successors.clear();
p.successors(&successors)
}
|p| p.chebyshev_distance(end),
|p| p == end,
);
Thoughts?
Thanks!
It looks like there are a few other allocations within the astar
implementation - just curious about the willingness or lack thereof to expose a way to avoid some of the ones that aren't necessary?
I haven't benchmarked my application (lots and lots of pathfinding) yet to see the difference in performance - so I'm mainly just throwing out an early question to get a sense of what has already been explored here vs. what has not.
Thanks!
The signature for successors
in astar()
is
successors: FN
where
FN: FnMut(&N) -> IN,
IN: IntoIterator<Item = (N, C)>,
This does not force you to allocate a vector. In fact, you could even implement IntoIterator
for a usize
-sized structure which would unsafely return the copy of an element in a vector that you reuse for every call to successors
. I modified an example and a test in commit e64b732 to make this clearer.
Concerning the other allocations, they are necessary in order to implement the A* algorithm. If you find more efficient implementations, I would gladly accept pull requests.
Ah silly me just reading the examples instead of car fully examining the functions! Thank you.
Hmmm maybe I’m missing something - but the BinaryHeap::new() call at the beginning of astar appears to be allocating - and to me it appears possible to provide that underlying Vec instead of creating it every time.
But my main issue was around successors - which you’ve helped me with already. I don’t plan to do any benchmarking for months but if I have any real hard numbers in the future I’ll come back to ya!
Thanks!