Skip to main content

linkrs_core/value/
memory.rs

1//! Memory Estimations for Value Types
2//!
3//! This module provides memory estimation for the Value enum and related types.
4
5use crate::types::memory_estimation::MemoryEstimatable;
6use crate::value::Value;
7
8impl MemoryEstimatable for Value {
9    fn estimate_memory(&self) -> usize {
10        let base_size = std::mem::size_of::<Value>();
11
12        match self {
13            // Fixed-size types
14            Value::Empty
15            | Value::Null(_)
16            | Value::Bool(_)
17            | Value::SmallInt(_)
18            | Value::Int(_)
19            | Value::BigInt(_)
20            | Value::Float(_)
21            | Value::Double(_) => base_size,
22
23            // Variable-length string types
24            Value::String(s) => base_size + s.len(),
25            Value::FixedString(data) => base_size + data.len(),
26
27            // Binary data
28            Value::Blob(b) => base_size + b.len(),
29
30            // Complex types with nested memory
31            Value::Decimal128(d) => base_size + std::mem::size_of_val(d),
32
33            // DateTime types
34            Value::Date(_) | Value::Time(_) | Value::DateTime(_) => base_size,
35
36            // Graph types
37            Value::Vertex(v) => base_size + std::mem::size_of_val(v.as_ref()),
38            Value::Edge(e) => base_size + std::mem::size_of_val(e.as_ref()),
39            Value::EdgeHeader(h) => base_size + std::mem::size_of_val(h.as_ref()),
40            Value::Path(p) => base_size + std::mem::size_of_val(p.as_ref()),
41
42            // Collection types (recursive)
43            Value::List(list) => {
44                base_size + list.iter().map(|v| v.estimate_memory()).sum::<usize>()
45            }
46            Value::Map(map) => {
47                base_size
48                    + map.capacity() * 8
49                    + map
50                        .iter()
51                        .map(|(k, v)| k.estimate_memory() + v.estimate_memory())
52                        .sum::<usize>()
53            }
54            Value::Set(set) => {
55                base_size
56                    + set.capacity() * 8
57                    + set.iter().map(|v| v.estimate_memory()).sum::<usize>()
58            }
59
60            // Geography type
61            Value::Geography(g) => base_size + std::mem::size_of_val(g),
62
63            // Vector type
64            Value::Vector(v) => base_size + v.estimated_size(),
65
66            // DataSet type
67            Value::DataSet(ds) => base_size + ds.as_ref().estimated_size(),
68
69            // JSON types
70            Value::Json(j) => base_size + j.estimated_size(),
71            Value::JsonB(j) => base_size + j.estimated_size(),
72
73            // UUID type (fixed size, 16 bytes)
74            Value::Uuid(_) => base_size,
75
76            // Interval type (fixed size)
77            Value::Interval(_) => base_size,
78
79            // Lightweight ID references (fixed size)
80            Value::VertexId(_) | Value::EdgeId(_) => base_size,
81
82            // Composite values (recursive)
83            Value::Struct(s) => {
84                base_size
85                    + s.fields
86                        .iter()
87                        .map(|(k, v)| k.len() + v.estimate_memory())
88                        .sum::<usize>()
89            }
90            Value::Array(a) => {
91                base_size + a.values.iter().map(|v| v.estimate_memory()).sum::<usize>()
92            }
93        }
94    }
95}
96
97/// Helper function to estimate memory for a slice of Values
98pub fn estimate_values_memory(values: &[Value]) -> usize {
99    values.iter().map(|v| v.estimate_memory()).sum()
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105
106    #[test]
107    fn test_fixed_size_value() {
108        let v = Value::Int(42);
109        assert_eq!(v.estimate_memory(), std::mem::size_of::<Value>());
110    }
111
112    #[test]
113    fn test_string_value() {
114        let s = compact_str::CompactString::new("hello");
115        let v = Value::String(s);
116        assert_eq!(v.estimate_memory(), std::mem::size_of::<Value>() + 5);
117    }
118
119    #[test]
120    fn test_list_value() {
121        use crate::value::list::List;
122        let list = vec![
123            Value::Int(1),
124            Value::Int(2),
125            Value::String(compact_str::CompactString::new("hello")),
126        ];
127        let v = Value::List(Box::new(List::from(list)));
128        let expected = std::mem::size_of::<Value>()
129            + std::mem::size_of::<Value>() * 2
130            + (std::mem::size_of::<Value>() + 5);
131        assert!(v.estimate_memory() >= expected);
132    }
133}