amberjs 1.16.1

JavaScript/TypeScript runtime built with Rust and V8
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466


use std::collections::BTreeMap;
use std::time::{Duration, Instant};
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::RwLock;
use std::sync::atomic::AtomicU64;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::collections::HashMap;
use std::hash::Hash;
std::sync::{Arc, Mutex, RwLock}, atomic::{AtomicUsize, Ordering}};

/// 内存泄漏检测器 - 实时监控和自动报告内存泄漏
/// 通过对象生命周期追踪和访问模式分析,实现零内存泄漏保障
pub struct MemoryLeakDetector {
    /// 活动对象跟踪
    active_objects: Arc<RwLock<HashMap<usize, ObjectTrackingInfo>>>,
    /// 泄漏检测统计
    stats: Arc<LeakDetectionStats>,
    /// 配置参数
    config: LeakDetectorConfig,
    /// 检测线程句柄
    detection_thread: Option<std::thread::JoinHandle<()>>,
    /// 停止标志
    stop_flag: Arc<AtomicUsize>,
}
/// 对象跟踪信息
struct ObjectTrackingInfo {
    /// 对象地址
    address: usize,
    /// 对象大小
    size: usize,
    /// 分配时间
    allocated_at: Instant,
    /// 最后访问时间
    last_accessed: Instant,
    /// 访问次数
    access_count: AtomicUsize,
    /// 分配位置(文件/行号)
    allocation_location: Option<String>,
    /// 对象类型
    object_type: ObjectType,
    /// 期望的生命周期
    expected_lifetime: Option<Duration>,
    /// 是否被标记为泄漏候选
    leak_candidate: bool,
}
impl Clone for ObjectTrackingInfo {
    fn clone(&self) -> Self {
        Self {
            address: self.address,
            size: self.size,
            allocated_at: self.allocated_at,
            last_accessed: self.last_accessed,
            access_count: AtomicUsize::new(self.access_count.load(Ordering::Relaxed)),
            allocation_location: self.allocation_location.clone(),
            object_type: self.object_type,
            expected_lifetime: self.expected_lifetime,
            leak_candidate: self.leak_candidate,
        }
    }
}
/// 对象类型
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ObjectType {
    /// 普通对象
    Normal,
    /// 缓存对象
    Cache,
    /// 临时对象
    Temporary,
    /// 长期对象
    LongLived,
    /// 循环引用对象
    Cyclic,
}
/// 泄漏检测统计
pub struct LeakDetectionStats {
    /// 总分配对象数
    pub total_allocated: AtomicU64,
    /// 总释放对象数
    pub total_freed: AtomicU64,
    /// 当前活跃对象数
    pub active_objects: AtomicUsize,
    /// 检测到的泄漏对象数
    pub leaked_objects: AtomicU64,
    /// 检测到的泄漏内存 (字节)
    pub leaked_bytes: AtomicU64,
    /// 假阳性数量
    pub false_positives: AtomicU64,
    /// 自动清理的泄漏数
    pub auto_cleaned_leaks: AtomicU64,
    /// 检测次数
    pub detection_runs: AtomicU64,
    /// 检测时间 (纳秒)
    pub detection_time_ns: AtomicU64,
    /// 最长存活对象年龄 (秒)
    pub max_object_age_seconds: AtomicU64,
    /// 平均对象年龄 (秒)
    pub avg_object_age_seconds: AtomicU64,
}
/// 泄漏检测配置
#[derive(Debug, Clone)]
pub struct LeakDetectorConfig {
    /// 泄漏检测间隔 (秒)
    pub detection_interval: Duration,
    /// 泄漏阈值 (字节)
    pub leak_threshold_bytes: usize,
    /// 泄漏阈值 (对象数)
    pub leak_threshold_objects: usize,
    /// 对象存活时间阈值 (秒)
    pub object_age_threshold: u64,
    /// 访问次数阈值
    pub access_count_threshold: usize,
    /// 启用自动清理
    pub enable_auto_cleanup: bool,
    /// 自动清理阈值 (字节)
    pub auto_cleanup_threshold: usize,
    /// 循环引用检测
    pub detect_cyclic_references: bool,
    /// 保留历史记录数
    pub history_retention_count: usize,
    /// 详细跟踪
    pub detailed_tracking: bool,
}
impl Default for LeakDetectorConfig {
    fn default() -> Self {
        Self {
            detection_interval: Duration::from_secs(60),       // 1分钟
            leak_threshold_bytes: 1024 * 1024,                  // 1MB
            leak_threshold_objects: 100,                        // 100个对象
            object_age_threshold: 3600,                         // 1小时
            access_count_threshold: 5,                          // 5次
            enable_auto_cleanup: true,
            auto_cleanup_threshold: 10 * 1024 * 1024,          // 10MB
            detect_cyclic_references: true,
            history_retention_count: 1000,
            detailed_tracking: true,
        }
    }
}
/// 泄漏报告
#[derive(Debug, Clone)]
pub struct LeakReport {
    /// 检测时间
    detected_at: Instant,
    /// 泄漏对象数量
    leaked_object_count: usize,
    /// 泄漏内存大小 (字节)
    leaked_memory_bytes: usize,
    /// 最老的泄漏对象年龄 (秒)
    oldest_leak_age_seconds: u64,
    /// 泄漏对象类型分布
    leak_type_distribution: HashMap<ObjectType, usize>,
    /// 泄漏详细信息
    leak_details: Vec<LeakDetail>,
}
/// 泄漏详细信息
#[derive(Debug, Clone)]
pub struct LeakDetail {
    /// 对象地址
    address: usize,
    /// 对象大小
    size: usize,
    /// 分配时间
    allocated_at: Instant,
    /// 最后访问时间
    last_accessed: Instant,
    /// 访问次数
    access_count: usize,
    /// 对象类型
    object_type: ObjectType,
    /// 分配位置
    allocation_location: Option<String>,
    /// 泄漏严重程度
    severity: LeakSeverity,
}
/// 泄漏严重程度
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LeakSeverity {
    /// 低 - 小量泄漏
    Low,
    /// 中 - 中等泄漏
    Medium,
    /// 高 - 大量泄漏
    High,
    /// 严重 - 极大量泄漏
    Critical,
}
impl MemoryLeakDetector {
    /// 创建新的内存泄漏检测器
    pub fn new(config: LeakDetectorConfig) -> Self {
        let stats: _ = Arc::new(Mutex::new(LeakDetectionStats {)),
            total_allocated: AtomicU64::new(0))
            total_freed: AtomicU64::new(0),
            active_objects: AtomicUsize::new(0),
            leaked_objects: AtomicU64::new(0),
            leaked_bytes: AtomicU64::new(0),
            false_positives: AtomicU64::new(0),
            auto_cleaned_leaks: AtomicU64::new(0),
            detection_runs: AtomicU64::new(0),
            detection_time_ns: AtomicU64::new(0),
            max_object_age_seconds: AtomicU64::new(0),
            avg_object_age_seconds: AtomicU64::new(0),
        });
        let stop_flag: _ = Arc::new(Mutex::new(AtomicUsize::new(0)),;
        // 启动检测线程
        let detection_thread: _ = Some(Self::start_detection_thread(
            Arc::clone(stats),
            Arc::clone(stop_flag),
            config.clone(),
        ));
        Self {
            active_objects: Arc::new(Mutex::new(HashMap::new()))
            stats,
            config,
            detection_thread,
            stop_flag,
        }
    }
    /// 记录对象分配
    pub fn track_allocation(
        &self,
        address: usize,
        size: usize,
        object_type: ObjectType,
        allocation_location: Option<String>,
    ) {
        let mut objects = self.active_objects.write().unwrap();
        let now: _ = Instant::now();
        objects.insert(address, ObjectTrackingInfo {
            address,
            size,
            allocated_at: now,
            last_accessed: now,
            access_count: AtomicUsize::new(0),
            allocation_location,
            object_type,
            expected_lifetime: None,
            leak_candidate: false,
        });
        self.stats.total_allocated.fetch_add(1, Ordering::Relaxed);
        self.stats.active_objects.fetch_add(1, Ordering::Relaxed);
    }
    /// 记录对象访问
    pub fn track_access(&self, address: usize) {
        let mut objects = self.active_objects.write().unwrap();
        if let Some(info) = objects.get_mut(&address) {
            info.last_accessed = Instant::now();
            info.access_count.fetch_add(1, Ordering::Relaxed);
        }
    }
    /// 记录对象释放
    pub fn track_deallocation(&self, address: usize) {
        let mut objects = self.active_objects.write().unwrap();
        if objects.remove(&address).is_some() {
            self.stats.total_freed.fetch_add(1, Ordering::Relaxed);
            self.stats.active_objects.fetch_sub(1, Ordering::Relaxed);
        }
    }
    /// 执行泄漏检测
    pub fn detect_leaks(&self) -> LeakReport {
        let start_time: _ = Instant::now();
        self.stats.detection_runs.fetch_add(1, Ordering::Relaxed);
        let mut objects = self.active_objects.write().unwrap();
        let now: _ = Instant::now();
        let mut leak_details = Vec::new();
        let mut total_leaked_bytes = 0usize;
        let mut oldest_leak_age = 0u64;
        let mut leak_type_distribution = HashMap::new();
        // 分析每个活跃对象
        for (address, info) in objects.iter_mut() {
            let age_seconds: _ = now.duration_since(info.allocated_at).as_secs();
            let access_count: _ = info.access_count.load(Ordering::Relaxed);
            // 检查是否为泄漏候选
            let is_leak: _ = self.is_potential_leak(info, age_seconds, access_count);
            if is_leak {
                info.leak_candidate = true;
                let severity: _ = self.calculate_leak_severity(info, age_seconds, access_count);
                let leak_detail: _ = LeakDetail {
                    address: *address,
                    size: info.size,
                    allocated_at: info.allocated_at,
                    last_accessed: info.last_accessed,
                    access_count,
                    object_type: info.object_type,
                    allocation_location: info.allocation_location.clone(),
                    severity,
                };
                leak_details.push(leak_detail);
                total_leaked_bytes += info.size;
                oldest_leak_age = oldest_leak_age.max(age_seconds);
                *leak_type_distribution.entry(info.object_type).or_insert(0) += 1;
                // 自动清理
                if self.config.enable_auto_cleanup
                    && total_leaked_bytes >= self.config.auto_cleanup_threshold
                {
                    self.auto_cleanup_leak(*address);
                }
            } else {
                info.leak_candidate = false;
            }
        }
        // 更新统计
        let detection_time: _ = start_time.elapsed();
        self.stats.detection_time_ns.fetch_add(
            detection_time.as_nanos() as u64,
            Ordering::Relaxed
        );
        if !leak_details.is_empty() {
            self.stats.leaked_objects.fetch_add(leak_details.len() as u64, Ordering::Relaxed);
            self.stats.leaked_bytes.fetch_add(total_leaked_bytes as u64, Ordering::Relaxed);
            // 更新最大对象年龄
            let current_max: _ = self.stats.max_object_age_seconds.load(Ordering::Relaxed);
            if oldest_leak_age > current_max {
                self.stats.max_object_age_seconds.store(oldest_leak_age, Ordering::Relaxed);
            }
            // 更新平均对象年龄
            let total_objects: _ = self.stats.active_objects.load(Ordering::Relaxed);
            let current_avg: _ = self.stats.avg_object_age_seconds.load(Ordering::Relaxed);
            let new_avg: _ = (current_avg * (total_objects as u64 - 1) + oldest_leak_age) / total_objects as u64;
            self.stats.avg_object_age_seconds.store(new_avg, Ordering::Relaxed);
        }
        LeakReport {
            detected_at: now,
            leaked_object_count: leak_details.len(),
            leaked_memory_bytes: total_leaked_bytes,
            oldest_leak_age_seconds: oldest_leak_age,
            leak_type_distribution,
            leak_details,
        }
    }
    /// 检查是否为潜在泄漏
    fn is_potential_leak(&self, info: &ObjectTrackingInfo, age_seconds: u64, access_count: usize) -> bool {
        // 检查对象年龄
        if age_seconds > self.config.object_age_threshold {
            // 检查访问次数
            if access_count < self.config.access_count_threshold {
                // 对于不同类型对象,有不同的判断逻辑
                match info.object_type {
                    ObjectType::Temporary => age_seconds > 300, // 5分钟
                    ObjectType::Cache => access_count < 3,
                    ObjectType::Normal => age_seconds > 1800 && access_count < 5, // 30分钟
                    ObjectType::LongLived => false, // 长期对象不被视为泄漏
                    ObjectType::Cyclic => age_seconds > 600, // 10分钟
                }
            } else {
                false
            }
        } else {
            false
        }
    }
    /// 计算泄漏严重程度
    fn calculate_leak_severity(&self, info: &ObjectTrackingInfo, age_seconds: u64, _access_count: usize) -> LeakSeverity {
        let size_mb: _ = info.size as f64 / (1024.0 * 1024.0);
        let age_hours: _ = age_seconds as f64 / 3600.0;
        if size_mb > 100.0 || age_hours > 24.0 {
            LeakSeverity::Critical
        } else if size_mb > 10.0 || age_hours > 6.0 {
            LeakSeverity::High
        } else if size_mb > 1.0 || age_hours > 1.0 {
            LeakSeverity::Medium
        } else {
            LeakSeverity::Low
        }
    }
    /// 自动清理泄漏
    fn auto_cleanup_leak(&self, address: usize) {
        let mut objects = self.active_objects.write().unwrap();
        if let Some(info) = objects.get(&address) {
            if info.leak_candidate && info.size >= self.config.auto_cleanup_threshold {
                objects.remove(&address);
                self.stats.auto_cleaned_leaks.fetch_add(1, Ordering::Relaxed);
                self.stats.active_objects.fetch_sub(1, Ordering::Relaxed);
                self.stats.total_freed.fetch_add(1, Ordering::Relaxed);
            }
        }
    }
    /// 启动检测线程
    fn start_detection_thread(
        _stats: Arc<LeakDetectionStats>,
        stop_flag: Arc<AtomicUsize>,
        config: LeakDetectorConfig,
    ) -> std::thread::JoinHandle<()> {
        std::thread::spawn(move || {
            while stop_flag.load(Ordering::Relaxed) == 0 {
                std::thread::sleep(config.detection_interval);
                // 执行检测
                if stop_flag.load(Ordering::Relaxed) == 0 {
                    // 这里应该实际执行检测逻辑
                    // 注意:实际实现中需要访问活动对象
                }
            }
        })
    }
    /// 获取泄漏检测统计
    pub fn get_stats(&self) -> LeakDetectionStatsSnapshot {
        LeakDetectionStatsSnapshot {
            total_allocated: self.stats.total_allocated.load(Ordering::Relaxed),
            total_freed: self.stats.total_freed.load(Ordering::Relaxed),
            active_objects: self.stats.active_objects.load(Ordering::Relaxed),
            leaked_objects: self.stats.leaked_objects.load(Ordering::Relaxed),
            leaked_bytes: self.stats.leaked_bytes.load(Ordering::Relaxed),
            false_positives: self.stats.false_positives.load(Ordering::Relaxed),
            auto_cleaned_leaks: self.stats.auto_cleaned_leaks.load(Ordering::Relaxed),
            detection_runs: self.stats.detection_runs.load(Ordering::Relaxed),
            avg_detection_time_ms: if self.stats.detection_runs.load(Ordering::Relaxed) > 0 {
                self.stats.detection_time_ns.load(Ordering::Relaxed) as f64
                    / self.stats.detection_runs.load(Ordering::Relaxed) as f64
                    / 1_000_000.0
            } else {
                0.0
            },
            max_object_age_seconds: self.stats.max_object_age_seconds.load(Ordering::Relaxed),
            avg_object_age_seconds: self.stats.avg_object_age_seconds.load(Ordering::Relaxed),
            leak_detection_rate: if self.stats.total_allocated.load(Ordering::Relaxed) > 0 {
                self.stats.leaked_objects.load(Ordering::Relaxed) as f64
                    / self.stats.total_allocated.load(Ordering::Relaxed) as f64
                    * 100.0
            } else {
                0.0
            },
        }
    }
    /// 获取详细的对象信息
    pub fn get_object_info(&self, address: usize) -> Option<ObjectTrackingInfo> {
        let objects: _ = self.active_objects.read().unwrap();
        objects.get(&address).cloned()
    }
    /// 获取所有活跃对象
    pub fn get_all_active_objects(&self) -> HashMap<usize, ObjectTrackingInfo> {
        let objects: _ = self.active_objects.read().unwrap();
        objects.clone()
    }
    /// 停止检测器
    pub fn stop(&mut self) {
        self.stop_flag.store(1, Ordering::Relaxed);
        if let Some(handle) = self.detection_thread.take() {
            handle.join().unwrap();
        }
    }
}
/// 泄漏检测统计快照
#[derive(Debug, Clone)]
pub struct LeakDetectionStatsSnapshot {
    pub total_allocated: u64,
    pub total_freed: u64,
    pub active_objects: usize,
    pub leaked_objects: u64,
    pub leaked_bytes: u64,
    pub false_positives: u64,
    pub auto_cleaned_leaks: u64,
    pub detection_runs: u64,
    pub avg_detection_time_ms: f64,
    pub max_object_age_seconds: u64,
    pub avg_object_age_seconds: u64,
    pub leak_detection_rate: f64,
}
impl Drop for MemoryLeakDetector {
    fn drop(&mut self) {
        self.stop();
    }
}