Possible optimization for dynamic-connectivity
btrekkie opened this issue ยท 8 comments
Describe your suggestion
Apologies, I wasn't sure where to post this. According to btrekkie/dynamic-connectivity#4 (comment) , @leijurv is considering incorporating a fork of https://github.com/btrekkie/dynamic-connectivity into Baritone. Based on a profiler screenshot in his comment, I thought of a potential optimization for this library.
I realized that Augmentation.combine
is called a lot, and in typical usage, it creates a new object each time it is called. I came up with this to reduce the number of object allocations: btrekkie/dynamic-connectivity@master...augmentation-pool . (Maybe start by looking at btrekkie/dynamic-connectivity@1586a7c#diff-06e896ad5b668fbe72375bf3a901e696429004e18c61104559fdde04d26360a7 and btrekkie/dynamic-connectivity@1586a7c#diff-1ff29087d4530c92b31fe61df3b855074ac0e88f4f54f6cd88bb441bc109e92fR163-R166 .) It would require switching from using Augmentation
to using MutatingAugmentation
. I wouldn't want to merge it into https://github.com/btrekkie/dynamic-connectivity without measuring its real-world performance, but I thought you might want to give it a try.
Also, you might try overriding Attachment.equals
, as this could reduce the number of calls to augment()
. (See https://github.com/btrekkie/dynamic-connectivity/blob/e7f54ab81da5cfd62908f870ccbfb68baec42b30/src/main/java/com/github/leijurv/NavigableSurface.java#L25 . )
Settings
N/A
Context
This could make things faster.
Final checklist
- I know how to properly use check boxes
- I have not used any OwO's or UwU's in this issue.
Oops, already replied here btrekkie/dynamic-connectivity@f378578#commitcomment-109123881
I have overridden Attachment.equals
I will try and merge this in when I get a chance. I wonder if git will allow me to merge this directly?
I was considering a few things for my use case and perhaps I should get more specialized. For example, I could replace the references to an augmentation object with just a function call in EulerTourNode.
Like:
@Override
public boolean augment() {
int newSize = left.size + right.size + 1;
I could just add my own fields here, and I would probably get blazing fast performance since it would be primitive fields rather than an entire augmentation object that needs to be allocated or pooled. I obviously understand that you probably wouldn't want that in your upstream repo because it's specialized and not a good abstraction. And it would make the code more icky and I'll probably only do it if I truly need the performance. But I think that would be the approach if I really needed to squeeze more out of this.
Another thought I had was here 8c11840#diff-982795ee3ff2c18759ea5167152094504af1cca0b0fbd4994271411f0d1e685cR25
My use case has no more than 4 edges attached to any given vertex (at most one each for north south east west). I think I might be able to improve performance by replacing the hashmap in VertexInfo with simply a ConnEdge[] edges = new ConnEdge[4]
then indexing into it with something like edges[Face.between(pos, neighborPos).horizontalIndex]
. (see
baritone/src/api/java/baritone/api/utils/BetterBlockPos.java
Lines 83 to 160 in 217f6ec
Curiosity got the better of me, so I took some more painkillers and merged in your commit. Thankfully, git let me do it, and it was actually very smart about putting the files in the right places even after I'd moved them all around! Only took a few minutes of fixing package
statements and simple merge conflicts.
Comparing 4bea9df (branch builder-2
) to 54e7473 (branch builder-2-mutating
), I sadly don't see any improvement in NavigableSurfaceTest
. It's still around 9.6 to 10 seconds give or take. If you have intellij, you should be able to open the baritone project, open NavigableSurfaceTest, then do "run current file" or "profile current file" to see this for yourself.
Before vs after comparison zoomed into one unit test:
Before vs after comparison zoomed into just removeEdge
of that unit test:
Dang, good to know.
I was able to run NavigableSurfaceTest
locally. Using MutatingAugmentation
reduces the number of Attachment
allocations from ~400 million to ~2 million, but has no significant effect on performance. I was really hoping for a simple ~50% reduction in running time.
Anyway, take it easy.
well, lowering allocations may still have more of an effect on some systems or java versions so it is probably still a good thing...
no yeah i think this is a good idea and it's moving in the right direction
i just want to go further and not have the attachments be separate at all. i want to inline them as primitive fields like EulerTourNode.size
is
Okay, after tinkering some more, I finally came up with something that significantly reduces the running time of NavigableSurfaceTest
: btrekkie/RedBlackNode@4dacba9 . In my testing, it reduced the running time by about 30% (after applying the bugfix at btrekkie/dynamic-connectivity@7c973bc ). I think this is mostly because it decreases the number of calls to augment()
by 40%.
Everything else I've tried so far has had an insignificant effect on the running time of NavigableSurfaceTest
, so it may have to wait until I have a more realistic benchmark of performance. (I didn't try moving the Attachment
field into EulerTourNode
or the VertexInfo.edges
optimization you mentioned, because they're not general changes that would be incorporated back into the dynamic-connectivity library.)
Wow!!! Fantastic. I have not been putting as much time as I'd like into builder-2 in the last few weeks, sorry - surgery, then, starting a new job next week. I hope to get back into it!
That's a great help and that makes a lot of sense given how much time is spent in augment
! Thank you so much!