-
-
Notifications
You must be signed in to change notification settings - Fork 6
Reduce allocations and internal copies #17
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
Conversation
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.
Pull Request Overview
A concise description of the purpose of the PR, followed by summarized bullets of changes
- Reduced dynamic allocations and struct copies by precomputing list capacities and using
in
parameters. - Switched the internal priority queue from a binary to a 4-ary heap with a one-pass heapify of unordered input.
- Updated benchmarks and tests to reflect the new queue construction and removed Clipper2 dependencies.
Reviewed Changes
Copilot reviewed 18 out of 20 changed files in this pull request and generated 1 comment.
Show a summary per file
File | Description |
---|---|
tests/TestData/Benchmarks/hole_hole.geojson | Added new GeoJSON file for benchmark test cases. |
tests/PolygonClipper.Tests/TestPolygonUtilitiesTests.cs | Removed Clipper2-specific tests and updated the union test to use profiled static polygons. |
tests/PolygonClipper.Tests/TestPolygonUtilities.cs | Dropped ConvertToClipper2Polygon helper and refined GeoJSON→Polygon conversion with a closure check. |
tests/PolygonClipper.Tests/TestData.cs | Introduced Benchmarks helper class to load GeoJSON files for benchmarks. |
tests/PolygonClipper.Tests/PolygonClipper.Tests.csproj | Removed obsolete Clipper2 NuGet package reference. |
tests/PolygonClipper.Benchmarks/PolygonClipper.Benchmarks.csproj | Removed Clipper2 reference and configured the benchmarks project. |
tests/PolygonClipper.Benchmarks/Benches.cs | Added Benches class to run BenchmarkDotNet benchmarks over multiple GeoJSON inputs. |
src/PolygonClipper/Vertex.cs | Added in modifiers to operator overloads and methods to avoid struct copies. |
src/PolygonClipper/SweepEvent.cs | Changed Below and Above to accept in Vertex p parameters. |
src/PolygonClipper/StatusLine.cs | Added capacity-taking constructor and preallocate list of sweep events. |
src/PolygonClipper/StablePriorityQueue{T,TComparer}.cs | Converted to 4-ary heap, added Log2Arity , Heapify , and list-based initial construction. |
src/PolygonClipper/SegmentComparer.cs | Removed redundant initializer for inversed flag. |
src/PolygonClipper/Segment.cs | Added in modifiers to constructor and equality operators. |
src/PolygonClipper/PolygonUtilities.cs | Added in modifiers to methods like SignedArea , MidPoint , and intersection helpers. |
src/PolygonClipper/PolygonClipper.cs | Changed sweep setup to build an unordered event list, then heapify; preallocated status line. |
src/PolygonClipper/Contour.cs | Updated AddVertex to take in Vertex . |
src/PolygonClipper/Box2.cs | Updated constructors and operators to take in Vertex . |
Comments suppressed due to low confidence (3)
src/PolygonClipper/StablePriorityQueue{T,TComparer}.cs:29
- This constructor initializes
heap
but does not assign theComparer
property, which could lead tothis.Comparer
being null if this overload is used. Consider addingthis.Comparer = comparer;
or removing this overload if it’s no longer needed.
public StablePriorityQueue(TComparer comparer, int capacity)
src/PolygonClipper/PolygonClipper.cs:389
- [nitpick] The parameter named
eventQueue
is actually aList<SweepEvent>
of unordered events, not a priority queue. Rename it toeventsList
orunorderedEvents
to reduce confusion.
e1.ContourId = e2.ContourId = contourId;
tests/PolygonClipper.Tests/TestPolygonUtilitiesTests.cs:38
- [nitpick] Test names should follow the
[MethodUnderTest_StateUnderTest_ExpectedBehavior]
pattern and avoid redundant_Test
suffixes. Consider renaming this to something likeUnion_WithPrebuiltPolygons_ReturnsExpectedContours
.
public void PolygonClipper_Union_Profile_Test()
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.
Should we add agressiveinlining to more getters in sweep event etc?
int clippingVertexCount = clipping.GetVertexCount(); | ||
int eventCount = (subjectVertexCount + clippingVertexCount) * 2; | ||
|
||
SweepEventComparer comparer = new(); |
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.
We could create a static comparer and then reuse it between runs?
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.
We could yeah. Or we could make it a struct, however allocation-wise it's absolutely tiny.
@@ -33,7 +33,7 @@ public static double SignedArea(Vertex p0, Vertex p1, Vertex p2) | |||
/// - Returns 1 if the segments intersect at a single point. | |||
/// - Returns 2 if the segments overlap. | |||
/// </returns> | |||
public static int FindIntersection(Segment seg0, Segment seg1, out Vertex pi0, out Vertex pi1) | |||
public static int FindIntersection(in Segment seg0, in Segment seg1, out Vertex pi0, out Vertex pi1) |
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.
Would using uint be beneficial here?
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.
No, it's just a count of the number of intersections, if anything it could be an enum.
Some more optimization work @stefannikolei
in
modifier forreadonly struct
parameters to avoid unnecessary copies.PriorityQueue
design for improved cache locality and shallower tree depth.I also removed Clipper2 from the benchmarks as I was unable to get reliable output from the geometry.
Benchmarks.
Main
PR
Comparison to other language implementations
rust-geo-booleanop
We're around .05x - 2.3x faster than the Rust implementation.
Martinez
We're around 2.7x - 3.8x faster than the JavaScript implementation.