-
Notifications
You must be signed in to change notification settings - Fork 448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve performance of HPRtree #1012
Conversation
Signed-off-by: Mike Barry <msb5014@gmail.com>
Signed-off-by: Mike Barry <msb5014@gmail.com>
Signed-off-by: Mike Barry <msb5014@gmail.com>
The code is certainly nicer with generics. Do you think the compile warnings are going to be obnoxious for downstream users? Generics have been asked for for a while for index containers, so maybe now is the time to add them. |
I don't think they would be too bad for consumers if it means they can get rid of instanceof checks and casting and don't cause any compile failures. I could go and update the other spatial index classes too. Think I should do that in this PR or a separate one? It might touch a lot of files. |
No, that should be done in a separate PR. Actually I'm still wondering if SpatialIndex generics are too much for this PR. I hate to lose all the work you've done - but perhaps you can move it to a different PR? |
No worries. Sounds good to keep this one focused on the performance improvements. I'll move generics out into another pr |
Signed-off-by: Mike Barry <msb5014@gmail.com>
For the generics PR, there are a bunch of things that it could include but it starts to get big pretty fast: parameterizing the external API of index classes
parameterizing the internal implementation of index classes
updating places in the code that use these indexes to benefit from the parameterized versions:
What do you think the scope of an initial PR should be? |
That's a great list, @msbarry.
Ideally - all of it! Or, at least |
Sorry, @msbarry , I've been delayed on getting on to merging this PR. Why does switching to using two arrays instead of |
@dr-jts thanks for getting back, I think it's because The biggest gain comes from Moving to That being said JVM performance often defies my intuition and this represents the fastest I could get the benchmarks and planetiler code that uses JTS a lot to run through mostly trial and error 😄 |
@msbarry did you port the Flatbush benchmark code? If so it would be nice to include that in this PR. Performance tests go in this package, and can use the performance test harness framework via PerformanceTestCase. |
Sure thing - I ported the tests over and have them run against STRTree and HPRtree. Here are the results from my 2021 m1 macbook pro in comparison to flatbush on node.js 20.3.0:
Raw hprtree/strtree benchmark output
Raw flatbush benchmark output❯ node bench
1000000 rectangles
node size: 16
+ flatbush: 178.922ms
index size: 38,400,092
+ 1000 searches 10%: 294.68ms
+ 1000 searches 1%: 37.187ms
+ 1000 searches 0.01%: 4.476ms
1000 searches of 100 neighbors: 18.683ms
1 searches of 1000000 neighbors: 111.913ms
100000 searches of 1 neighbors: 482.469ms
rbush: 843.683ms
1000 searches 10%: 640.872ms
1000 searches 1%: 155.409ms
1000 searches 0.01%: 17.523ms
1000 searches of 100 neighbors: 47.962ms
1 searches of 1000000 neighbors: 271.478ms
100000 searches of 1 neighbors: 1.212s Since Flatbush builds in ~180ms but HPRtree takes ~250ms there may be more room for improvement when building... It looks like of those 250ms, it's:
|
Hello, just checking in here, are there any other tests to run or changes to make before merging this? |
No, I think this looks good. I'll merge soon. |
While profiling performance of planetiler I noticed that STRtree in MCIndexNoder was one of the bottlenecks. I looked into HPRtree and saw there were a few opportunities to improve performance using some ideas from the flatbush library:
This version performs faster in some of the microbenchmarks (especially when result sets are large) but when I swap out STRtree with this improved HPRtree planetiler spends about 30% less time in MCIndexNoder.computeNodes, isValid checks, and about 10% less time in the most expensive operations planetiler uses: GeometryPrecisionReducer.reduce and bufferUnionUnbuffer.