Skip to content

v2.1: Improve performance by ~35 times#127

Merged
mourner merged 7 commits into
masterfrom
faster
Jun 25, 2026
Merged

v2.1: Improve performance by ~35 times#127
mourner merged 7 commits into
masterfrom
faster

Conversation

@mourner

@mourner mourner commented Jun 24, 2026

Copy link
Copy Markdown
Member

Performance-focused rewrite of the core distance computation:

  • Edge-block bbox skip: group each ring's edges into blocks of 32 consecutive edges and precompute one bounding box per block (a single flat Float64Array, sized upfront; block layout is re-derived in the scan from coords/ringEnds, so no auxiliary index arrays). In the per-cell distance scan, a cheap point-to-bbox lower bound skips a whole block in O(1) when it can neither beat the current nearest distance nor flip the ray-cast parity. Polygon rings are spatially coherent, so most blocks are far from any given cell center and get skipped wholesale.
  • Flattened coordinate buffer. Rings are copied once into a single contiguous Float64Array (coords) with per-ring end offsets (ringEnds), replacing nested array-of-[x, y] iteration. This removes pointer-chasing in the hot distance loop for cache-friendly access.
  • Early-exit distance scan. pointToPolygonDist now takes a distance threshold (maxD). A cell is only useful if it can beat the current best or is worth subdividing; once the center is provably within the threshold of the outline, the scan bails out early instead of measuring the whole outline.
  • Nearest-segment seeding. Each cell records the nearest segment found during its scan. When a cell is split, its four children seed their scan with the parent's nearest segment — a child is almost always nearest to the same segment, so boundary cells hit the early-out threshold immediately.

@mourner mourner requested a review from a team as a code owner June 24, 2026 21:20
@mourner mourner requested review from ibesora and removed request for a team and ibesora June 24, 2026 21:20
@mourner mourner marked this pull request as draft June 24, 2026 21:21
@mourner mourner changed the title v2.1: Improve performance by ~2.5 times v2.1: Improve performance by ~35 times Jun 24, 2026
@mourner mourner marked this pull request as ready for review June 25, 2026 07:56
@mourner mourner merged commit 2a95a36 into master Jun 25, 2026
2 checks passed
urschrei added a commit to urschrei/polylabel-rs that referenced this pull request Jun 28, 2026
Decompose each ring into edges grouped into fixed-size blocks (BLOCK_SIZE=32),
precomputing one bounding box per block once per polylabel call (PreparedPolygon).
The per-cell distance scan uses a cheap point-to-bbox lower bound to skip a whole
block when it can neither hold a nearer edge nor flip the ray-cast parity. The
per-segment distance is still geo's Euclidean point-to-Line; only the AABB lower
bound is computed inline (geo's point-to-Rect allocates per call).

See also: mapbox/polylabel#127


Signed-off-by: Stephan Hügel <shugel@tcd.ie>
urschrei added a commit to urschrei/polylabel-rs that referenced this pull request Jun 28, 2026
Decompose each ring into edges grouped into fixed-size blocks (BLOCK_SIZE=32),
precomputing one bounding box per block once per polylabel call (PreparedPolygon).
The per-cell distance scan uses a cheap point-to-bbox lower bound to skip a whole
block when it can neither hold a nearer edge nor flip the ray-cast parity. The
per-segment distance is still geo's Euclidean point-to-Line; only the AABB lower
bound is computed inline (geo's point-to-Rect allocates per call).

See also: mapbox/polylabel#127


Signed-off-by: Stephan Hügel <shugel@tcd.ie>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant