fix: batch 1 — deadlock, AVX-512 gating, Windows case-collisions

Closes #437: VectorDb::delete in ruvector-router-core acquired the stats
RwLock twice in one statement. parking_lot::RwLock is non-reentrant, so
the second .write() deadlocked against the first guard's lifetime. Bind
the guard once.

Closes #438: Gate AVX-512 intrinsics behind a new `simd-avx512` Cargo
feature (default-on). Lets downstream consumers on stable Rust 1.77–1.88
(before avx512f stabilization in 1.89) opt out without forcing nightly:
  cargo build --no-default-features --features simd,storage,hnsw,api-embeddings,parallel
Runtime dispatch falls back to AVX2 + FMA when the feature is disabled.
All 4 #[target_feature(enable = "avx512f")] sites + 4 dispatch branches
updated. Both feature configurations verified to compile cleanly; all
18 simd_intrinsics tests pass.

Closes #458: Rename two pairs of case-colliding research artifacts under
docs/research/claude-code-rvsource/versions/v2.1.x/tree/react_memo_cache_sentinel/
that broke `git clone` on Windows/NTFS:
  tmux.js → tmux_lc.js   (TMUX.js kept)
  type.js → type_lc.js   (Type.js kept)
modules-manifest.json updated to match.

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
ruvnet 2026-05-16 08:30:31 -04:00
parent 9054c2cc67
commit 0fa88d61b2
6 changed files with 42 additions and 20 deletions

View file

@ -95,8 +95,13 @@ name = "bench_memory"
harness = false
[features]
default = ["simd", "storage", "hnsw", "api-embeddings", "parallel"]
default = ["simd", "simd-avx512", "storage", "hnsw", "api-embeddings", "parallel"]
simd = ["simsimd"] # SIMD acceleration (not available in WASM)
# AVX-512 intrinsics. Requires Rust >= 1.89 (where avx512f stabilized).
# Downstream consumers on older stable (1.771.88) can opt out:
# --no-default-features --features simd,storage,hnsw,api-embeddings,parallel
# See issue #438.
simd-avx512 = []
parallel = ["rayon", "crossbeam"] # Parallel processing (not available in WASM)
storage = ["redb", "memmap2"] # File-based storage (not available in WASM)
hnsw = ["hnsw_rs"] # HNSW indexing (not available in WASM due to mmap dependency)

View file

@ -42,9 +42,13 @@ const PREFETCH_DISTANCE: usize = 64;
pub fn euclidean_distance_simd(a: &[f32], b: &[f32]) -> f32 {
#[cfg(target_arch = "x86_64")]
{
if is_x86_feature_detected!("avx512f") {
unsafe { euclidean_distance_avx512_impl(a, b) }
} else if is_x86_feature_detected!("avx2") && is_x86_feature_detected!("fma") {
#[cfg(feature = "simd-avx512")]
{
if is_x86_feature_detected!("avx512f") {
return unsafe { euclidean_distance_avx512_impl(a, b) };
}
}
if is_x86_feature_detected!("avx2") && is_x86_feature_detected!("fma") {
unsafe { euclidean_distance_avx2_fma_impl(a, b) }
} else if is_x86_feature_detected!("avx2") {
unsafe { euclidean_distance_avx2_impl(a, b) }
@ -192,7 +196,7 @@ unsafe fn euclidean_distance_avx2_fma_impl(a: &[f32], b: &[f32]) -> f32 {
// ============================================================================
/// AVX-512 euclidean distance - processes 16 floats per iteration
#[cfg(target_arch = "x86_64")]
#[cfg(all(target_arch = "x86_64", feature = "simd-avx512"))]
#[target_feature(enable = "avx512f")]
unsafe fn euclidean_distance_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
assert_eq!(a.len(), b.len(), "Input arrays must have the same length");
@ -223,7 +227,7 @@ unsafe fn euclidean_distance_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
}
/// AVX-512 dot product - processes 16 floats per iteration
#[cfg(target_arch = "x86_64")]
#[cfg(all(target_arch = "x86_64", feature = "simd-avx512"))]
#[target_feature(enable = "avx512f")]
unsafe fn dot_product_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
assert_eq!(a.len(), b.len(), "Input arrays must have the same length");
@ -249,7 +253,7 @@ unsafe fn dot_product_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
}
/// AVX-512 cosine similarity - processes 16 floats per iteration
#[cfg(target_arch = "x86_64")]
#[cfg(all(target_arch = "x86_64", feature = "simd-avx512"))]
#[target_feature(enable = "avx512f")]
unsafe fn cosine_similarity_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
assert_eq!(a.len(), b.len(), "Input arrays must have the same length");
@ -284,7 +288,7 @@ unsafe fn cosine_similarity_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
}
/// AVX-512 Manhattan distance - processes 16 floats per iteration
#[cfg(target_arch = "x86_64")]
#[cfg(all(target_arch = "x86_64", feature = "simd-avx512"))]
#[target_feature(enable = "avx512f")]
unsafe fn manhattan_distance_avx512_impl(a: &[f32], b: &[f32]) -> f32 {
assert_eq!(a.len(), b.len(), "Input arrays must have the same length");
@ -783,9 +787,13 @@ unsafe fn manhattan_distance_neon_unrolled_impl(a: &[f32], b: &[f32]) -> f32 {
pub fn dot_product_simd(a: &[f32], b: &[f32]) -> f32 {
#[cfg(target_arch = "x86_64")]
{
if is_x86_feature_detected!("avx512f") {
unsafe { dot_product_avx512_impl(a, b) }
} else if is_x86_feature_detected!("avx2") {
#[cfg(feature = "simd-avx512")]
{
if is_x86_feature_detected!("avx512f") {
return unsafe { dot_product_avx512_impl(a, b) };
}
}
if is_x86_feature_detected!("avx2") {
unsafe { dot_product_avx2_impl(a, b) }
} else {
dot_product_scalar(a, b)
@ -847,9 +855,13 @@ unsafe fn dot_product_avx2_impl(a: &[f32], b: &[f32]) -> f32 {
pub fn cosine_similarity_simd(a: &[f32], b: &[f32]) -> f32 {
#[cfg(target_arch = "x86_64")]
{
if is_x86_feature_detected!("avx512f") {
unsafe { cosine_similarity_avx512_impl(a, b) }
} else if is_x86_feature_detected!("avx2") {
#[cfg(feature = "simd-avx512")]
{
if is_x86_feature_detected!("avx512f") {
return unsafe { cosine_similarity_avx512_impl(a, b) };
}
}
if is_x86_feature_detected!("avx2") {
unsafe { cosine_similarity_avx2_impl(a, b) }
} else {
cosine_similarity_scalar(a, b)
@ -883,9 +895,13 @@ pub fn cosine_similarity_avx2(a: &[f32], b: &[f32]) -> f32 {
pub fn manhattan_distance_simd(a: &[f32], b: &[f32]) -> f32 {
#[cfg(target_arch = "x86_64")]
{
if is_x86_feature_detected!("avx512f") {
unsafe { manhattan_distance_avx512_impl(a, b) }
} else if is_x86_feature_detected!("avx2") {
#[cfg(feature = "simd-avx512")]
{
if is_x86_feature_detected!("avx512f") {
return unsafe { manhattan_distance_avx512_impl(a, b) };
}
}
if is_x86_feature_detected!("avx2") {
unsafe { manhattan_distance_avx2_impl(a, b) }
} else {
manhattan_distance_scalar(a, b)

View file

@ -150,7 +150,8 @@ impl VectorDB {
if deleted {
self.index.remove(id)?;
self.stats.write().total_vectors = self.stats.write().total_vectors.saturating_sub(1);
let mut stats = self.stats.write();
stats.total_vectors = stats.total_vectors.saturating_sub(1);
}
Ok(deleted)

View file

@ -1418,7 +1418,7 @@
"size": 387
},
{
"name": "type.js",
"name": "type_lc.js",
"size": 387
},
{
@ -2330,7 +2330,7 @@
"size": 176
},
{
"name": "tmux.js",
"name": "tmux_lc.js",
"size": 176
},
{