Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions docs/dev/debug_env_vars.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,18 @@ and release builds.
| `DELAUNAY_LARGE_DEBUG_BALL_RADIUS` | **value** | Radius for ball distribution |
| `DELAUNAY_LARGE_DEBUG_BOX_HALF_WIDTH` | **value** | Half-width for box distribution |
| `DELAUNAY_LARGE_DEBUG_CONSTRUCTION_MODE` | **value** | `new` (batch) or `incremental` |
| `DELAUNAY_LARGE_DEBUG_DEBUG_MODE` | **value** | `cadenced` or `strict` |
| `DELAUNAY_LARGE_DEBUG_INITIAL_SIMPLEX` | **value** | Batch initial simplex strategy: `first` (default) or `balanced` |
| `DELAUNAY_LARGE_DEBUG_DEBUG_MODE` | **value** | `cadenced` (ridge-link) or `strict` (per-insertion vertex-link) |
| `DELAUNAY_LARGE_DEBUG_SHUFFLE_SEED` | **value** | Vertex shuffle seed |
| `DELAUNAY_LARGE_DEBUG_PROGRESS_EVERY` | **value** | Progress logging interval |
| `DELAUNAY_LARGE_DEBUG_VALIDATE_EVERY` | **value** | Validation interval |
| `DELAUNAY_LARGE_DEBUG_REPAIR_EVERY` | **value** | Repair interval |
| `DELAUNAY_LARGE_DEBUG_REPAIR_EVERY` | **value** | Batch/incremental repair interval (default: 4) |
| `DELAUNAY_LARGE_DEBUG_REPAIR_MAX_FLIPS` | **value** | Flip budget override |
| `DELAUNAY_LARGE_DEBUG_MAX_RUNTIME_SECS` | **value** | Timeout (0 = no cap) |
| `DELAUNAY_LARGE_DEBUG_ALLOW_SKIPS` | presence | Allow vertex insertion skips |
| `DELAUNAY_LARGE_DEBUG_MAX_SKIP_PCT` | **value** | Maximum skipped-vertex percentage before failing (default: 5.0) |
| `DELAUNAY_LARGE_DEBUG_ALLOW_SKIPS` | presence | Allow any number of vertex insertion skips |
| `DELAUNAY_LARGE_DEBUG_SKIP_FINAL_REPAIR` | presence | Skip final global repair pass |
| `DELAUNAY_BATCH_REPAIR_TRACE` | presence | Trace cadenced batch-repair seed counts, flips, queues, and elapsed time |
| `DELAUNAY_LARGE_DEBUG_PREFIX_TOTAL` | **value** | Total prefix probes for bisect mode |
| `DELAUNAY_LARGE_DEBUG_PREFIX_MAX_PROBES` | **value** | Max probes per bisect run |
| `DELAUNAY_LARGE_DEBUG_PREFIX_MAX_RUNTIME_SECS` | **value** | Bisect probe timeout |
Expand Down
59 changes: 55 additions & 4 deletions src/core/algorithms/locate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,21 @@ impl LocateStats {
}
}

/// Internal locate result that also records the final cell reached by the walk.
///
/// Exterior insertion uses `terminal_cell` as a local conflict-region seed so it
/// can avoid a full triangulation scan while still repairing cells near the hull
/// facet where point location exited the triangulation.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct LocateTrace {
/// Public location classification.
pub(crate) result: LocateResult,
/// Public locate diagnostics.
pub(crate) stats: LocateStats,
/// Last cell visited by the facet walk before returning or falling back.
pub(crate) terminal_cell: CellKey,
}

/// Locate a point in the triangulation using facet walking (correctness-first).
///
/// This function attempts a fast facet-walking traversal starting from `hint` (when provided).
Expand Down Expand Up @@ -802,6 +817,26 @@ pub fn locate_with_stats<K, U, V, const D: usize>(
point: &Point<K::Scalar, D>,
hint: Option<CellKey>,
) -> Result<(LocateResult, LocateStats), LocateError>
where
K: Kernel<D>,
U: DataType,
V: DataType,
{
let trace = locate_with_trace(tds, kernel, point, hint)?;
Ok((trace.result, trace.stats))
}

/// Locate a point and keep the final walked cell for local exterior repair.
///
/// This mirrors [`locate_with_stats`] but also exposes the last facet-walk cell
/// before the algorithm concluded. For [`LocateResult::Outside`] without a scan
/// fallback, that cell is adjacent to the hull facet crossed by the query point.
pub(crate) fn locate_with_trace<K, U, V, const D: usize>(
tds: &Tds<K::Scalar, U, V, D>,
kernel: &K,
point: &Point<K::Scalar, D>,
hint: Option<CellKey>,
) -> Result<LocateTrace, LocateError>
where
K: Kernel<D>,
U: DataType,
Expand Down Expand Up @@ -842,7 +877,11 @@ where
steps: stats.walk_steps,
});
let result = locate_by_scan(tds, kernel, point)?;
return Ok((result, stats));
return Ok(LocateTrace {
result,
stats,
terminal_cell: current_cell,
});
}

let cell = tds.cell(current_cell).ok_or(LocateError::InvalidCell {
Expand All @@ -863,12 +902,20 @@ where
found_outside_facet = true;
break;
}
return Ok((LocateResult::Outside, stats));
return Ok(LocateTrace {
result: LocateResult::Outside,
stats,
terminal_cell: current_cell,
});
}
}

if !found_outside_facet {
return Ok((LocateResult::InsideCell(current_cell), stats));
return Ok(LocateTrace {
result: LocateResult::InsideCell(current_cell),
stats,
terminal_cell: current_cell,
});
}
}

Expand All @@ -877,7 +924,11 @@ where
steps: stats.walk_steps,
});
let result = locate_by_scan(tds, kernel, point)?;
Ok((result, stats))
Ok(LocateTrace {
result,
stats,
terminal_cell: current_cell,
})
}

pub(crate) fn locate_by_scan<K, U, V, const D: usize>(
Expand Down
68 changes: 68 additions & 0 deletions src/core/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,74 @@ impl InsertionStatistics {
}
}

/// Release-visible telemetry for one transactional insertion.
///
/// These counters are intended for aggregate diagnostics rather than stable performance
/// benchmarking. They let batch construction report whether insertion time is dominated by
/// point location, scan fallbacks, local conflict regions, or global exterior-point scans.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub(crate) struct InsertionTelemetry {
/// Number of point-location calls performed for this insertion.
pub locate_calls: usize,
/// Total facet-walk steps across all point-location calls.
pub locate_walk_steps_total: usize,
/// Maximum facet-walk steps taken by a single point-location call.
pub locate_walk_steps_max: usize,
/// Number of point-location calls that used the caller-provided hint.
pub locate_hint_uses: usize,
/// Number of point-location calls that fell back to a brute-force scan.
pub locate_scan_fallbacks: usize,
/// Number of point-location calls that ended inside a cell.
pub located_inside: usize,
/// Number of point-location calls that ended outside the convex hull.
pub located_outside: usize,
/// Number of point-location calls that ended on a lower-dimensional feature.
pub located_on_boundary: usize,

/// Number of local conflict-region computations observed by insertion.
pub conflict_region_calls: usize,
/// Total number of cells in local conflict regions.
pub conflict_region_cells_total: usize,
/// Maximum number of cells in a single local conflict region.
pub conflict_region_cells_max: usize,
/// Wall-clock nanoseconds spent computing local conflict regions.
pub conflict_region_nanos: u64,
/// Maximum wall-clock nanoseconds spent computing one local conflict region.
pub conflict_region_nanos_max: u64,

/// Number of cavity insertion attempts observed by insertion.
pub cavity_insertion_calls: usize,
/// Wall-clock nanoseconds spent filling cavities and wiring neighbors.
pub cavity_insertion_nanos: u64,
/// Maximum wall-clock nanoseconds spent in one cavity insertion attempt.
pub cavity_insertion_nanos_max: u64,

/// Number of hull extension attempts observed by insertion.
pub hull_extension_calls: usize,
/// Wall-clock nanoseconds spent extending the convex hull.
pub hull_extension_nanos: u64,
/// Maximum wall-clock nanoseconds spent in one hull extension attempt.
pub hull_extension_nanos_max: u64,

/// Number of post-insertion topology validations observed by insertion.
pub topology_validation_calls: usize,
/// Wall-clock nanoseconds spent in post-insertion topology validation.
pub topology_validation_nanos: u64,
/// Maximum wall-clock nanoseconds spent in one post-insertion validation.
pub topology_validation_nanos_max: u64,

/// Number of global exterior-point conflict scans.
pub global_conflict_scans: usize,
/// Total cells scanned by global exterior-point conflict scans.
pub global_conflict_cells_scanned: usize,
/// Total cells found by global exterior-point conflict scans.
pub global_conflict_cells_found_total: usize,
/// Maximum cells found by a single global exterior-point conflict scan.
pub global_conflict_cells_found_max: usize,
/// Wall-clock nanoseconds spent in global exterior-point conflict scans.
pub global_conflict_scan_nanos: u64,
}

/// Ephemeral insertion state used by Delaunay triangulations.
#[derive(Clone, Copy, Debug)]
pub(crate) struct DelaunayInsertionState {
Expand Down
Loading
Loading