mirror of
https://github.com/qdrant/qdrant.git
synced 2026-08-02 08:00:55 -05:00
* Add mincore-based memory stats to MmapFile Add `resident_bytes()`, `disk_bytes()`, and `probe_memory_stats()` methods to `MmapFile` for measuring page cache residency via `mincore(2)`. This is the foundation for per-collection memory usage reporting. Also extract `page_size()` as a public function in `mmap::advice`, replacing the internal `PAGE_SIZE_MASK` with a direct page size cache. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] introduce trait for reporting memory usage per component * [AI] memory reporter implementation for vector storage * [AI] implement MemoryReporter for QuantizedVectors * [AI] implement MemoryReporter for VectorIndexEnum * Implement MemoryReporter for IdTrackerEnum with RAM estimation Add ram_usage_bytes() to all ID tracker types and their data structures: - PointMappings, CompressedPointMappings, CompressedVersions, CompressedInternalToExternal, CompressedExternalToInternal - MutableIdTracker, ImmutableIdTracker, InMemoryIdTracker All ID trackers load their data into RAM (none use mmap for working data). Files are reported as OnDisk (persistence only), actual RAM footprint is reported via extra_ram_bytes. Uses struct destructuring to ensure new fields trigger compile errors if not accounted for. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] implement MemoryReporter for PayloadStorageEnum and adjust FileStorageIntent * [AI] implement MemoryReporter for PayloadStorageEnum and adjust FileStorageIntent * [AI] implement MemoryReporter for payload indexes: in-ram structures memory consumtion computation + caching * [AI] implement MemoryReporter for payload indexes: in-ram structures memory consumtion computation + caching * [AI] segment-level memory usage report * [AI] Block 3: Aggregation Layer and Data Model + internal api for remote shard * [AI] REST API handler * fmt * [AI] clippy fixes * [AI] macos fix + proxy segment fix * [AI] make text index estimation a bit more correct * fix is_on_disk reporting for dense_vector_storage * fix after rebase * [AI] deep account for quantized vectors RAM usage + unify chunk size + shring volatile storage after load * remove debug log * cache in test * make manual test easier to run * rollback chunk size diff, but keep it for test only * review fixes * Use exhaustive match * Use div_ceil on bits everywhere It does not seem to be strictly necessary because the number of bits should already be a multiple of the used container size bytes. Still it's good practice to be careful with this calculation. * Improve heap size bytes for encoded product quantization vectors * Include vector stats for binary quantized vectors * In volatile chunked vectors, include heap allocated vector * Include rest of heap allocated structures for mutable map index * In mutable geo index, the hash map is also heap allocated * Update tests/manual/test_memory_reporting.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: timvisee <tim@visee.me> Co-authored-by: Tim Visée <tim+github@visee.me> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
94 lines
2.9 KiB
Rust
94 lines
2.9 KiB
Rust
use std::path::PathBuf;
|
|
|
|
/// Describes how a component expects its files to be used.
|
|
///
|
|
/// Used to compute `expected_cache_bytes` and label components for users.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum FileStorageIntent {
|
|
/// Data may or may not be in RAM, residency managed by OS page cache.
|
|
Cached,
|
|
/// Data is on disk, not expected to be in RAM.
|
|
OnDisk,
|
|
}
|
|
|
|
/// A single file with its storage intent.
|
|
#[derive(Debug, Clone)]
|
|
pub struct ComponentFileEntry {
|
|
pub path: PathBuf,
|
|
pub intent: FileStorageIntent,
|
|
}
|
|
|
|
/// Memory usage reported by a single component.
|
|
///
|
|
/// Components return file entries (with intent metadata) and optionally
|
|
/// an estimate of additional heap RAM not backed by files.
|
|
#[derive(Debug, Clone)]
|
|
pub struct ComponentMemoryUsage {
|
|
/// Files owned by this component with their storage intent.
|
|
pub files: Vec<ComponentFileEntry>,
|
|
/// Additional RAM not backed by files (e.g., in-memory data structures).
|
|
pub extra_ram_bytes: Option<u64>,
|
|
}
|
|
|
|
impl ComponentMemoryUsage {
|
|
/// Convenience: empty report (no files, no extra RAM).
|
|
pub fn empty() -> Self {
|
|
Self {
|
|
files: Vec::new(),
|
|
extra_ram_bytes: None,
|
|
}
|
|
}
|
|
|
|
/// Convenience: report only non-file RAM usage.
|
|
pub fn ram_only(bytes: u64) -> Self {
|
|
Self {
|
|
files: Vec::new(),
|
|
extra_ram_bytes: Some(bytes),
|
|
}
|
|
}
|
|
|
|
/// Convenience: report files with a uniform intent and no extra RAM.
|
|
pub fn from_files(paths: Vec<PathBuf>, intent: FileStorageIntent) -> Self {
|
|
Self {
|
|
files: paths
|
|
.into_iter()
|
|
.map(|path| ComponentFileEntry { path, intent })
|
|
.collect(),
|
|
extra_ram_bytes: None,
|
|
}
|
|
}
|
|
|
|
/// Report files with a uniform intent plus additional non-file RAM.
|
|
pub fn from_files_and_ram(
|
|
paths: Vec<PathBuf>,
|
|
intent: FileStorageIntent,
|
|
extra_ram_bytes: u64,
|
|
) -> Self {
|
|
Self {
|
|
files: paths
|
|
.into_iter()
|
|
.map(|path| ComponentFileEntry { path, intent })
|
|
.collect(),
|
|
extra_ram_bytes: Some(extra_ram_bytes),
|
|
}
|
|
}
|
|
|
|
/// Merge another report into this one (concatenate files, sum RAM).
|
|
pub fn merge(&mut self, other: &ComponentMemoryUsage) {
|
|
self.files.extend(other.files.iter().cloned());
|
|
match (self.extra_ram_bytes, other.extra_ram_bytes) {
|
|
(Some(a), Some(b)) => self.extra_ram_bytes = Some(a + b),
|
|
(None, Some(b)) => self.extra_ram_bytes = Some(b),
|
|
(_, None) => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Trait for components to report their memory footprint.
|
|
///
|
|
/// Implementations should be cheap (no I/O). The actual `mincore` measurement
|
|
/// happens in the aggregation layer after file entries are collected.
|
|
pub trait MemoryReporter {
|
|
fn memory_usage(&self) -> ComponentMemoryUsage;
|
|
}
|