Skip to content

perf(vector/search): naN handling in float heaps via unwrap_or(Ordering::Equal) — silent reorder risk #667

@mosuka

Description

@mosuka

Round-3 perf push sub-issue (tracked under umbrella #536).

[S] NaN handling in float heaps via unwrap_or(Ordering::Equal) — silent reorder risk

  • Where: hnsw/searcher.rs:270-310, vector/store.rs:480-495, engine.rs:1485. All
    use partial_cmp(...).unwrap_or(Ordering::Equal).
  • Current behavior: A NaN distance gets treated as equal to everything → heap invariant
    silently broken → possible wrong top-K. Kernel emits NaN-free values today but a single
    bad input via fallback path would corrupt the heap.
  • Reference precedent: ordered_float::NotNan; Lucene asserts non-NaN; Qdrant uses
    f32::total_cmp.
  • Suggested direction: Use f32::total_cmp (Rust 1.62+) for deterministic order, or
    validate at kernel boundary. Wrap heap items in NotNanF32 newtype. With the packed
    candidate (above), this is automatic.
  • Risk / scope: Small.

ID: VS-24 — see ~/.claude/tasks/laurus/20260523_perf_round3_audit/task_list.md for the full Round-3 issue list.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions