1use crate::core::clone_monitor;
7use crate::core::optimized_types::OptimizedAllocationInfo;
8use crate::core::types::AllocationInfo;
9use std::sync::Arc;
10
11pub fn share_allocation_info(info: AllocationInfo) -> Arc<OptimizedAllocationInfo> {
13 let optimized = OptimizedAllocationInfo::from(info);
14 let size = std::mem::size_of::<OptimizedAllocationInfo>();
15
16 clone_monitor::record_optimized_clone("AllocationInfo", size);
17 Arc::new(optimized)
18}
19
20pub fn clone_shared_allocation(
22 arc_info: &Arc<OptimizedAllocationInfo>,
23) -> Arc<OptimizedAllocationInfo> {
24 let size = std::mem::size_of::<OptimizedAllocationInfo>();
25 clone_monitor::record_avoided_clone("AllocationInfo", size);
26 Arc::clone(arc_info)
27}
28
29pub fn unshare_allocation_info(arc_info: Arc<OptimizedAllocationInfo>) -> AllocationInfo {
31 match Arc::try_unwrap(arc_info) {
33 Ok(optimized) => optimized.into(),
34 Err(arc_info) => (*arc_info).clone().into(),
35 }
36}
37
38pub fn share_allocation_vector(
40 infos: Vec<AllocationInfo>,
41) -> Arc<Vec<Arc<OptimizedAllocationInfo>>> {
42 let shared_infos: Vec<Arc<OptimizedAllocationInfo>> =
43 infos.into_iter().map(share_allocation_info).collect();
44
45 Arc::new(shared_infos)
46}
47
48pub fn should_use_arc_sharing(type_name: &str, size: usize) -> bool {
50 size > 1024
52 || type_name.contains("AllocationInfo")
53 || type_name.contains("Config")
54 || type_name.contains("Result")
55 || type_name.contains("Collection")
56}
57
58pub fn optimized_clone<T>(value: &T) -> T
60where
61 T: Clone + 'static,
62{
63 let type_name = std::any::type_name::<T>();
64 let size = std::mem::size_of::<T>();
65
66 if should_use_arc_sharing(type_name, size) {
67 clone_monitor::record_clone(type_name, size, 0);
70 value.clone()
71 } else {
72 let start = std::time::Instant::now();
74 let result = value.clone();
75 let duration = start.elapsed().as_nanos() as u64;
76 clone_monitor::record_clone(type_name, size, duration);
77 result
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use crate::core::types::AllocationInfo;
85
86 fn create_test_allocation_info(ptr: usize, size: usize) -> AllocationInfo {
88 AllocationInfo {
89 ptr,
90 size,
91 var_name: Some(format!("test_var_{ptr}")),
92 type_name: Some("TestType".to_string()),
93 scope_name: None,
94 timestamp_alloc: 1000000,
95 timestamp_dealloc: None,
96 thread_id: "test_thread".to_string(),
97 borrow_count: 0,
98 stack_trace: None,
99 is_leaked: false,
100 lifetime_ms: None,
101 borrow_info: None,
102 clone_info: None,
103 ownership_history_available: false,
104 smart_pointer_info: None,
105 memory_layout: None,
106 generic_info: None,
107 dynamic_type_info: None,
108 runtime_state: None,
109 stack_allocation: None,
110 temporary_object: None,
111 fragmentation_analysis: None,
112 generic_instantiation: None,
113 type_relationships: None,
114 type_usage: None,
115 function_call_tracking: None,
116 lifecycle_tracking: None,
117 access_tracking: None,
118 drop_chain_analysis: None,
119 }
120 }
121
122 #[test]
123 fn test_share_allocation_info() {
124 let info = create_test_allocation_info(0x1000, 1024);
126 let shared = share_allocation_info(info);
127
128 assert_eq!(shared.ptr, 0x1000);
129 assert_eq!(shared.size, 1024);
130 assert_eq!(
131 shared.var_name.as_ref().map(|s| s.as_ref()),
132 Some("test_var_4096")
133 );
134 }
135
136 #[test]
137 fn test_clone_shared_allocation() {
138 let info = create_test_allocation_info(0x2000, 2048);
140 let shared = share_allocation_info(info);
141
142 let cloned = clone_shared_allocation(&shared);
144
145 assert_eq!(Arc::strong_count(&shared), 2);
147 assert_eq!(shared.ptr, cloned.ptr);
148 assert_eq!(shared.size, cloned.size);
149 }
150
151 #[test]
152 fn test_unshare_allocation_info_single_reference() {
153 let info = create_test_allocation_info(0x3000, 512);
155 let original_ptr = info.ptr;
156 let original_size = info.size;
157
158 let shared = share_allocation_info(info);
159 assert_eq!(Arc::strong_count(&shared), 1);
160
161 let unshared = unshare_allocation_info(shared);
162 assert_eq!(unshared.ptr, original_ptr);
163 assert_eq!(unshared.size, original_size);
164 }
165
166 #[test]
167 fn test_unshare_allocation_info_multiple_references() {
168 let info = create_test_allocation_info(0x4000, 256);
170 let shared = share_allocation_info(info);
171 let _cloned = Arc::clone(&shared);
172
173 assert_eq!(Arc::strong_count(&shared), 2);
174
175 let unshared = unshare_allocation_info(shared);
177 assert_eq!(unshared.ptr, 0x4000);
178 assert_eq!(unshared.size, 256);
179 }
180
181 #[test]
182 fn test_share_allocation_vector() {
183 let infos = vec![
185 create_test_allocation_info(0x5000, 128),
186 create_test_allocation_info(0x6000, 256),
187 create_test_allocation_info(0x7000, 512),
188 ];
189
190 let shared_vec = share_allocation_vector(infos);
191
192 assert_eq!(shared_vec.len(), 3);
193 assert_eq!(shared_vec[0].ptr, 0x5000);
194 assert_eq!(shared_vec[1].ptr, 0x6000);
195 assert_eq!(shared_vec[2].ptr, 0x7000);
196 }
197
198 #[test]
199 fn test_should_use_arc_sharing_by_size() {
200 assert!(should_use_arc_sharing("SomeType", 2048)); assert!(!should_use_arc_sharing("SomeType", 512)); assert!(!should_use_arc_sharing("TinyType", 64)); }
205
206 #[test]
207 fn test_should_use_arc_sharing_by_type_name() {
208 assert!(should_use_arc_sharing("AllocationInfo", 100));
210 assert!(should_use_arc_sharing("SomeConfig", 100));
211 assert!(should_use_arc_sharing("QueryResult", 100));
212 assert!(should_use_arc_sharing("DataCollection", 100));
213
214 assert!(!should_use_arc_sharing("SimpleStruct", 100));
216 }
217
218 #[test]
219 fn test_optimized_clone_small_type() {
220 let small_value = 42u32;
222 let cloned = optimized_clone(&small_value);
223 assert_eq!(cloned, 42);
224 }
225
226 #[test]
227 fn test_optimized_clone_string() {
228 let test_string = "Test string for cloning".to_string();
230 let cloned = optimized_clone(&test_string);
231 assert_eq!(cloned, test_string);
232 }
233
234 #[test]
235 fn test_optimized_clone_vector() {
236 let test_vec = vec![1, 2, 3, 4, 5];
238 let cloned = optimized_clone(&test_vec);
239 assert_eq!(cloned, test_vec);
240 }
241
242 #[test]
243 fn test_arc_reference_counting() {
244 let info = create_test_allocation_info(0x8000, 1024);
246 let shared1 = share_allocation_info(info);
247
248 assert_eq!(Arc::strong_count(&shared1), 1);
249
250 let shared2 = clone_shared_allocation(&shared1);
251 assert_eq!(Arc::strong_count(&shared1), 2);
252 assert_eq!(Arc::strong_count(&shared2), 2);
253
254 let shared3 = clone_shared_allocation(&shared2);
255 assert_eq!(Arc::strong_count(&shared1), 3);
256 assert_eq!(Arc::strong_count(&shared2), 3);
257 assert_eq!(Arc::strong_count(&shared3), 3);
258
259 drop(shared3);
260 assert_eq!(Arc::strong_count(&shared1), 2);
261
262 drop(shared2);
263 assert_eq!(Arc::strong_count(&shared1), 1);
264 }
265}