Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:

steps:
- uses: actions/checkout@v1
- uses: dtolnay/rust-toolchain@1.85
- uses: dtolnay/rust-toolchain@1.89
- uses: actions-rs/cargo@v1
with:
command: build
Expand All @@ -41,7 +41,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: dtolnay/rust-toolchain@1.85
- uses: dtolnay/rust-toolchain@1.89
with:
profile: minimal
components: clippy, rustfmt
Expand Down
5 changes: 2 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "arroy"
description = "Annoy-inspired Approximate Nearest Neighbors in Rust, based on LMDB and optimized for memory usage"
version = "0.6.3"
version = "0.6.4-nested-rtxns"
documentation = "https://docs.rs/arroy"
repository = "https://github.com/meilisearch/arroy"
keywords = ["ANN-search", "Graph-algorithms", "Vector-Search", "Store"]
Expand All @@ -16,7 +16,7 @@ edition = "2021"
[dependencies]
bytemuck = { version = "1.21.0", features = ["derive", "extern_crate_alloc"] }
byteorder = "1.5.0"
heed = { version = "0.22.0", default-features = false }
heed = { version = "0.22.1-nested-rtxns", default-features = false }
tracing = "0.1.41"
memmap2 = "0.9.5"
ordered-float = "4.6.0"
Expand All @@ -35,7 +35,6 @@ approx = "0.5.1"
arbitrary = { version = "1.4.1", features = ["derive"] }
clap = { version = "4.5.24", features = ["derive"] }
env_logger = "0.11.6"
hannoy = "0.0.4"
insta = "1.42.0"
instant-distance = "0.6.1"
proptest = "1.6.0"
Expand Down
2 changes: 1 addition & 1 deletion src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl<'a> heed::BytesEncode<'a> for MetadataCodec {

fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<'a, [u8]>, BoxedError> {
let Metadata { dimensions, items, roots, distance } = item;
debug_assert!(!distance.as_bytes().iter().any(|&b| b == 0));
debug_assert!(!distance.as_bytes().contains(&0));

let mut output = Vec::with_capacity(
size_of::<u32>()
Expand Down
2 changes: 1 addition & 1 deletion src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ impl<'t, D: Distance> Reader<'t, D> {
/// Return a [`QueryBuilder`] that lets you configure and execute a search request.
///
/// You must provide the number of items you want to receive.
pub fn nns(&self, count: usize) -> QueryBuilder<D> {
pub fn nns(&self, count: usize) -> QueryBuilder<'_, D> {
QueryBuilder { reader: self, count, search_k: None, oversampling: None, candidates: None }
}

Expand Down
2 changes: 1 addition & 1 deletion src/roaring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl heed::BytesDecode<'_> for RoaringBitmapCodec {
impl heed::BytesEncode<'_> for RoaringBitmapCodec {
type EItem = RoaringBitmap;

fn bytes_encode(item: &Self::EItem) -> Result<Cow<[u8]>, BoxedError> {
fn bytes_encode(item: &Self::EItem) -> Result<Cow<'_, [u8]>, BoxedError> {
let mut bytes = Vec::with_capacity(item.serialized_size());
item.serialize_into(&mut bytes)?;
Ok(Cow::Owned(bytes))
Expand Down
4 changes: 2 additions & 2 deletions src/spaces/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ pub fn dot_product_non_optimized(u: &UnalignedVector<f32>, v: &UnalignedVector<f
///
/// 2. Then we need to do the sum of the results:
/// 2.1 First we must do the sum of the operation on the `Word`s
/// /!\ We must be careful here because `1 - 0` actually translates to `1 - 1 = 0`.
/// `word.count_ones() - word.count_zeroes()` should do it:
/// /!\ We must be careful here because `1 - 0` actually translates to `1 - 1 = 0`.
/// `word.count_ones() - word.count_zeroes()` should do it:
/// ```text
/// 00 => -2
/// 01 => 0
Expand Down
2 changes: 1 addition & 1 deletion src/tests/binary_quantized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fn write_and_retrieve_binary_quantized_vector() {
==================
Dumping index 0
Root: Metadata { dimensions: 16, items: RoaringBitmap<[0]>, roots: [0], distance: "binary quantized euclidean" }
Version: Version { major: 0, minor: 6, patch: 3 }
Version: Version { major: 0, minor: 6, patch: 4 }
Tree 0: Descendants(Descendants { descendants: [0] })
Item 0: Leaf(Leaf { header: NodeHeaderBinaryQuantizedEuclidean { bias: 0.0 }, vector: [-1.0000, -1.0000, 1.0000, -1.0000, 1.0000, 1.0000, -1.0000, 1.0000, -1.0000, -1.0000, "other ..."] })
"###);
Expand Down
117 changes: 28 additions & 89 deletions src/tests/writer.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/unaligned_vector/binary_quantized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const QUANTIZED_WORD_BYTES: usize = std::mem::size_of::<QuantizedWord>();
pub enum BinaryQuantized {}

impl UnalignedVectorCodec for BinaryQuantized {
fn from_bytes(bytes: &[u8]) -> Result<Cow<UnalignedVector<Self>>, SizeMismatch> {
fn from_bytes(bytes: &[u8]) -> Result<Cow<'_, UnalignedVector<Self>>, SizeMismatch> {
let rem = bytes.len() % QUANTIZED_WORD_BYTES;
if rem == 0 {
// safety: `UnalignedVector` is transparent
Expand Down Expand Up @@ -94,7 +94,7 @@ unsafe fn from_slice_neon(slice: &[f32]) -> Vec<u8> {
// The size of the returned vector must be a multiple of a word
let remaining = slice.len() % QUANTIZED_WORD_BYTES;
let mut len = iterations;
if len % QUANTIZED_WORD_BYTES != 0 {
if !len.is_multiple_of(QUANTIZED_WORD_BYTES) {
len += QUANTIZED_WORD_BYTES - len % QUANTIZED_WORD_BYTES;
} else if remaining != 0 {
// if we generated a valid number of Word but we're missing a few bits
Expand Down
10 changes: 4 additions & 6 deletions src/unaligned_vector/f32.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::{
borrow::Cow,
mem::{size_of, transmute},
};
use std::borrow::Cow;
use std::mem::{size_of, transmute};

use bytemuck::cast_slice;
use byteorder::{ByteOrder, NativeEndian};
Expand All @@ -10,7 +8,7 @@ use super::{SizeMismatch, UnalignedVector, UnalignedVectorCodec};

impl UnalignedVectorCodec for f32 {
/// Creates an unaligned slice of f32 wrapper from a slice of bytes.
fn from_bytes(bytes: &[u8]) -> Result<Cow<UnalignedVector<Self>>, SizeMismatch> {
fn from_bytes(bytes: &[u8]) -> Result<Cow<'_, UnalignedVector<Self>>, SizeMismatch> {
let rem = bytes.len() % size_of::<f32>();
if rem == 0 {
// safety: `UnalignedF32Slice` is transparent
Expand All @@ -22,7 +20,7 @@ impl UnalignedVectorCodec for f32 {

/// Creates an unaligned slice of f32 wrapper from a slice of f32.
/// The slice is already known to be of the right length.
fn from_slice(slice: &[f32]) -> Cow<UnalignedVector<Self>> {
fn from_slice(slice: &[f32]) -> Cow<'_, UnalignedVector<Self>> {
Self::from_bytes(cast_slice(slice)).unwrap()
}

Expand Down
19 changes: 8 additions & 11 deletions src/unaligned_vector/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use std::{
borrow::{Borrow, Cow},
fmt,
marker::PhantomData,
mem::transmute,
};
use std::borrow::{Borrow, Cow};
use std::fmt;
use std::marker::PhantomData;
use std::mem::transmute;

pub use binary_quantized::BinaryQuantized;

use bytemuck::pod_collect_to_vec;

mod binary_quantized;
Expand All @@ -19,11 +16,11 @@ mod binary_quantized_test;
pub trait UnalignedVectorCodec: std::borrow::ToOwned + Sized {
/// Creates an unaligned vector from a slice of bytes.
/// Don't allocate.
fn from_bytes(bytes: &[u8]) -> Result<Cow<UnalignedVector<Self>>, SizeMismatch>;
fn from_bytes(bytes: &[u8]) -> Result<Cow<'_, UnalignedVector<Self>>, SizeMismatch>;

/// Creates an unaligned vector from a slice of f32.
/// May allocate depending on the codec.
fn from_slice(slice: &[f32]) -> Cow<UnalignedVector<Self>>;
fn from_slice(slice: &[f32]) -> Cow<'_, UnalignedVector<Self>>;

/// Creates an unaligned slice of f32 wrapper from a slice of f32.
/// The slice is already known to be of the right length.
Expand Down Expand Up @@ -64,13 +61,13 @@ impl<Codec: UnalignedVectorCodec> UnalignedVector<Codec> {

/// Creates an unaligned vector from a slice of bytes.
/// Don't allocate.
pub fn from_bytes(bytes: &[u8]) -> Result<Cow<UnalignedVector<Codec>>, SizeMismatch> {
pub fn from_bytes(bytes: &[u8]) -> Result<Cow<'_, UnalignedVector<Codec>>, SizeMismatch> {
Codec::from_bytes(bytes)
}

/// Creates an unaligned vector from a slice of f32.
/// May allocate depending on the codec.
pub fn from_slice(slice: &[f32]) -> Cow<UnalignedVector<Codec>> {
pub fn from_slice(slice: &[f32]) -> Cow<'_, UnalignedVector<Codec>> {
Codec::from_slice(slice)
}

Expand Down
2 changes: 1 addition & 1 deletion src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ impl<D: Distance> Writer<D> {
tmp_nodes,
)?;

return Ok((new_id, new_items));
Ok((new_id, new_items))
}
}
NodeMode::Tree => {
Expand Down
Loading