VectorSharp.Storage 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package VectorSharp.Storage --version 1.0.0
                    
NuGet\Install-Package VectorSharp.Storage -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="VectorSharp.Storage" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="VectorSharp.Storage" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="VectorSharp.Storage" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add VectorSharp.Storage --version 1.0.0
                    
#r "nuget: VectorSharp.Storage, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package VectorSharp.Storage@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=VectorSharp.Storage&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=VectorSharp.Storage&version=1.0.0
                    
Install as a Cake Tool

VectorSharp

A high-performance, zero-dependency .NET library for in-process vector similarity search. Supports both in-memory and disk-backed storage with SIMD-optimized cosine similarity.

Why VectorSharp?

Most vector search solutions require running a separate service, Docker containers, or pulling in heavy native dependencies. VectorSharp is a single NuGet package that works in-process. No infrastructure, no external processes, no native binaries.

  • Zero dependencies - just one NuGet install
  • In-process - runs inside your application, no separate service
  • High performance - SIMD-optimized similarity with automatic parallelization
  • Disk-backed storage - memory-mapped files for datasets that don't fit in RAM
  • Multi-store search - query across multiple stores in a single call
  • Generic keys - use int, long, Guid, or any unmanaged struct as identifiers
  • Thread-safe - concurrent reads with exclusive writes

Install

dotnet add package VectorSharp.Storage

Quick Start

using VectorSharp.Storage;

// Create an in-memory store (768 is a common embedding dimension)
CosineVectorStore<int> store = VectorStore.Create<int>("my-store", 768);

// Add vectors with your own IDs
await store.AddAsync(1, embeddingVector);
await store.AddAsync(2, anotherVector);

// Find similar vectors
IReadOnlyList<SearchResult<int>> results = await store.FindMostSimilarAsync(queryVector, count: 10);

foreach (SearchResult<int> result in results)
{
    Console.WriteLine($"ID: {result.Id}, Score: {result.Score}");
}

Core Concepts

Vector Stores

A vector store holds vectors and supports similarity search. VectorSharp provides two implementations behind a shared interface:

// In-memory - fast, limited by available RAM
CosineVectorStore<int> memoryStore = VectorStore.Create<int>("my-store", 768);

// Disk-backed - uses memory-mapped files, handles larger datasets
DiskVectorStore<int> diskStore = VectorStore.OpenFile<int>("my-store", "vectors.dat", 768);

Both implement IVectorStore<TKey> and can be used interchangeably.

Key Types

The key type is generic - use whatever identifier your data already has. The constraint is where TKey : unmanaged, IEquatable<TKey>, which covers the common cases:

// Integer keys (e.g. database primary keys)
IVectorStore<int> store = VectorStore.Create<int>("store", 768);

// Long keys
IVectorStore<long> store = VectorStore.Create<long>("store", 768);

// Guid keys
IVectorStore<Guid> store = VectorStore.Create<Guid>("store", 768);

Search Results

Search results are sorted by similarity score (highest first) and include the store name so you know where each result came from:

IReadOnlyList<SearchResult<int>> results = await store.FindMostSimilarAsync(queryVector, count: 5);

SearchResult<int> best = results[0];
// best.Id       - your key (int, Guid, etc.)
// best.Score    - cosine similarity score
// best.StoreName - "my-store"

Search across multiple stores in a single call. Results are merged by score and the global top-K is returned:

IVectorStore<int> codebaseA = VectorStore.Create<int>("codebase-a", 768);
IVectorStore<int> codebaseB = VectorStore.Create<int>("codebase-b", 768);
DiskVectorStore<int> archive = VectorStore.OpenFile<int>("archive", "archive.dat", 768);

// Search one
IReadOnlyList<SearchResult<int>> results = await codebaseA.FindMostSimilarAsync(query, 10);

// Search any combination
IReadOnlyList<SearchResult<int>> results = await VectorSearch.SearchAsync(query, 10, codebaseA, codebaseB);

// Search all three (including mixed in-memory and disk-backed)
IReadOnlyList<SearchResult<int>> results = await VectorSearch.SearchAsync(
    query, 10, codebaseA, codebaseB, archive);

Each store is queried in parallel. Results include StoreName so you know which store each hit came from.

Disk-Backed Storage

For datasets too large for RAM, use DiskVectorStore. It uses memory-mapped files for sequential scan search - the OS page cache handles caching transparently:

// Create or open a disk-backed store
DiskVectorStore<int> store = VectorStore.OpenFile<int>("large-store", "vectors.dat", 768);

// Same API as in-memory
await store.AddAsync(42, embeddingVector);
IReadOnlyList<SearchResult<int>> results = await store.FindMostSimilarAsync(queryVector, 10);

// Remove marks the record as deleted (excluded from search)
await store.RemoveAsync(42);

// Compact rewrites the file without deleted records to reclaim space
await store.CompactAsync();

// Always dispose when done (cleans up memory-mapped file handles)
store.Dispose();

Building a Disk Store from an In-Memory Store

You can build vectors in memory and then save to disk format:

// Build in memory
CosineVectorStore<int> memStore = VectorStore.Create<int>("builder", 768);
foreach (MyDocument doc in documents)
{
    float[] embedding = await embedder.EmbedAsync(doc.Content);
    await memStore.AddAsync(doc.Id, embedding);
}

// Save to disk
using (FileStream fs = File.Create("vectors.dat"))
{
    await memStore.SaveAsync(fs);
}

// Open as disk-backed store
DiskVectorStore<int> diskStore = VectorStore.OpenFile<int>("docs", "vectors.dat", 768);

The binary format is shared - files saved by CosineVectorStore can be opened by DiskVectorStore and vice versa.

Persistence

In-memory stores can be saved to and loaded from any stream:

CosineVectorStore<Guid> store = VectorStore.Create<Guid>("my-store", 768);

// Save
using (FileStream fs = File.Create("vectors.dat"))
{
    await store.SaveAsync(fs);
}

// Load (replaces current contents)
using (FileStream fs = File.OpenRead("vectors.dat"))
{
    await store.LoadAsync(fs);
}

Typical Usage Pattern

VectorSharp stores vectors and returns your keys. Your existing database stores the actual content. This keeps the vector store compact - just IDs and float arrays:

// Your data lives in Postgres (or wherever)
MyDocument doc = await repository.GetByIdAsync(docId);
float[] embedding = await embedder.EmbedAsync(doc.Content);

// Vector store only holds the ID and embedding
await vectorStore.AddAsync(doc.Id, embedding);

// Search returns IDs - you fetch content from your own database
IReadOnlyList<SearchResult<int>> results = await vectorStore.FindMostSimilarAsync(queryEmbedding, 10);
foreach (SearchResult<int> result in results)
{
    MyDocument matched = await repository.GetByIdAsync(result.Id);
    Console.WriteLine($"Score: {result.Score:F3} - {matched.Title}");
}

Performance

Benchmarked with 10,000 vectors at 768 dimensions:

Operation Performance
In-memory search ~5 ms/query
Disk-backed search ~7 ms/query
Concurrent search ~1.6 ms/query
Insertion ~285,000 vectors/sec
Save to file ~170,000 vectors/sec
Load from file ~830,000 vectors/sec

Disk-backed search is only ~1.3x slower than in-memory when the OS page cache is warm (typical for repeated searches against the same store).

Memory Usage

Vectors (768-dim) Approximate Memory
1,000 ~3 MB
10,000 ~30 MB
100,000 ~300 MB

When to Use VectorSharp

VectorSharp is designed for in-process vector search with up to a few hundred thousand vectors. If you need to search millions of vectors, distributed sharding, or sub-millisecond latency at scale, use a dedicated vector database.

API Reference

IVectorStore<TKey>

public interface IVectorStore<TKey> : IDisposable
    where TKey : unmanaged, IEquatable<TKey>
{
    string Name { get; }
    int Dimension { get; }
    int Count { get; }

    Task AddAsync(TKey id, float[] values);
    Task<bool> RemoveAsync(TKey id);
    Task<IReadOnlyList<SearchResult<TKey>>> FindMostSimilarAsync(float[] queryVector, int count);
}

SearchResult<TKey>

public readonly struct SearchResult<TKey>
{
    public TKey Id { get; }
    public float Score { get; }
    public string StoreName { get; }
}

VectorStore (Factory)

public static class VectorStore
{
    public static CosineVectorStore<TKey> Create<TKey>(string name, int dimension);
    public static DiskVectorStore<TKey> OpenFile<TKey>(string name, string filePath, int dimension);
}

VectorSearch

public static class VectorSearch
{
    public static Task<IReadOnlyList<SearchResult<TKey>>> SearchAsync<TKey>(
        float[] queryVector, int count, params IVectorStore<TKey>[] stores);
}

CosineVectorStore<TKey> (additional methods)

public Task SaveAsync(Stream stream);
public Task LoadAsync(Stream stream);

DiskVectorStore<TKey> (additional methods)

public Task CompactAsync();

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.0 185 4/20/2026
1.1.0 174 4/19/2026
1.0.0 108 4/18/2026