-
Notifications
You must be signed in to change notification settings - Fork 182
Rewrote A* to be faster with fewer allocations. #1231
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1231 +/- ##
==========================================
+ Coverage 99.62% 99.67% +0.04%
==========================================
Files 94 94
Lines 4311 4323 +12
==========================================
+ Hits 4295 4309 +14
+ Misses 16 14 -2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty solid! Can you post some benchmarks? Where did you find the performance gains?
Thanks! Here's the benchmark I ran using the following graph:
And here are the results I got: OLD
NEW
So maybe a bit better than what I reported above :P As for where we got the improvement, there were two major areas:
Both of these can be seen in the attached ProfileView graph of the old method (the big red pyramid on the left is the concatenation, the towers on the right are priority queue hashing): whereas our new implementation has its runtime cost spread out over many different underlying functions: Unfortunately, I can't upload the actual SVG outputs, but you could obtain these by running
(just know that for the old method, you'll have to change the |
I really appreciate your attention to detail in the code and the benchmarks. Once we have tests passing (not your fault; we have randomness in a few functions that causes failures sometimes) I'm happy to merge this. Thank you. |
This happened quite fast, so I don't know if there is a point in still doing a code review. One thing that I noticed is, that the result type will change from Also, when doing benchmarks, one should maybe also do some with non-constant edge weights and a non-constant heuristic. For profiling, I think there is a command, that can increase the number of samples collected. |
Anything that gives us a 3 orders of magnitude speedup on SimpleGraphs is a no-brainer to me. As far as the return value goes, my opinion is that the latter ( If there is metadata on the edge, it should have reasonable default values. The algorithm does not claim to create or preserve metadata of the returned edges. (Perhaps we should consider a As far as benchmarks, you're right that more formal benchmarking is nice, but I have not seen that in many PRs; in fact, this is some of the most thorough benchmarking and analysis I've seen for any PR in recent memory and would like to encourage this sort of output. If there is a specific objection to the code – if you've found a regression – then I'm all ears and we should revisit. But as it stands, we've got a massive improvement in speed and it passes all our current tests. |
Apologies, if that came over as some harsh criticism, that was never the intention and the comment on the benchmark should be seen more as some kind of feedback, as it should be clear from the code changes, that this code will run faster. There are two problems with using The second one is, that the algorithm uses the constructor
I can create a PR to change that to the old behaviour. |
MHO is that the problem is not with this code, it is with the fact that |
This fixes it for SWG:
|
Rewrote A* to more closely follow widely-adopted implementations, greatly speeding up its runtime (roughly 200x faster) and reducing its memory usage (roughly 300x fewer allocations and size of allocations).