amberjs 1.17.0

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


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::time::SystemTime;
std::sync::{Arc, Mutex, RwLock}, atomic::{AtomicUsize, Ordering}};

/// 分代垃圾回收器 - 基于对象生命周期的智能垃圾回收
/// 通过分代策略和并发回收,最小化 GC 停顿时间,提升性能
pub struct GenerationalGC {
    /// 年轻代 - 短生命周期对象
    young_gen: Arc<RwLock<YoungGeneration>>,
    /// 老年代 - 长生命周期对象
    old_gen: Arc<RwLock<OldGeneration>>,
    /// 统计信息
    stats: Arc<GCStats>,
    /// 配置参数
    config: GCConfig,
    /// GC 线程句柄
    gc_thread: Option<thread::JoinHandle<()>>,
    /// 停止标志
    stop_flag: Arc<AtomicUsize>,
}
/// 年轻代 - 新创建的对象首先进入此代
#[derive(Debug)]
struct YoungGeneration {
    /// 活跃对象集合
    live_objects: HashMap<usize, ObjectInfo>,
    /// 空闲空间
    free_space: usize,
    /// 总空间
    total_space: usize,
    /// 创建时间
    created_at: Instant,
    /// 最后 GC 时间
    last_gc: Instant,
}
/// 老年代 - 从年轻代晋升的长生命周期对象
#[derive(Debug)]
struct OldGeneration {
    /// 活跃对象集合
    live_objects: HashMap<usize, ObjectInfo>,
    /// 总空间
    total_space: usize,
    /// 压缩统计
    compaction_count: AtomicUsize,
    /// 创建时间
    created_at: Instant,
}
/// 对象信息
#[derive(Debug, Clone)]
struct ObjectInfo {
    /// 对象地址
    address: usize,
    /// 对象大小
    size: usize,
    /// 创建时间
    created_at: Instant,
    /// 最后访问时间
    last_accessed: Instant,
    /// 年龄(年轻代回收次数)
    age: usize,
    /// 晋升阈值
    promotion_threshold: usize,
}
/// GC 统计信息
pub struct GCStats {
    /// 年轻代 GC 次数
    pub young_gc_count: AtomicU64,
    /// 老年代 GC 次数
    pub old_gc_count: AtomicU64,
    /// 总回收对象数
    pub total_collected_objects: AtomicU64,
    /// 总回收内存 (字节)
    pub total_collected_bytes: AtomicU64,
    /// 总 GC 停顿时间 (纳秒)
    pub total_pause_time_ns: AtomicU64,
    /// 最大 GC 停顿时间 (纳秒)
    pub max_pause_time_ns: AtomicU64,
    /// 晋升对象数
    pub promoted_objects: AtomicU64,
    /// 晋升失败次数
    pub promotion_failures: AtomicU64,
}
impl Default for GCStats {
    fn default() -> Self {
        Self {
            young_gc_count: AtomicU64::new(0),
            old_gc_count: AtomicU64::new(0),
            total_collected_objects: AtomicU64::new(0),
            total_collected_bytes: AtomicU64::new(0),
            total_pause_time_ns: AtomicU64::new(0),
            max_pause_time_ns: AtomicU64::new(0),
            promoted_objects: AtomicU64::new(0),
            promotion_failures: AtomicU64::new(0),
        }
    }
}
/// GC 配置
#[derive(Debug, Clone)]
pub struct GCConfig {
    /// 年轻代初始大小 (字节)
    pub young_gen_size: usize,
    /// 年轻代最大大小 (字节)
    pub young_gen_max_size: usize,
    /// 老年代初始大小 (字节)
    pub old_gen_size: usize,
    /// 老年代最大大小 (字节)
    pub old_gen_max_size: usize,
    /// 年轻代 GC 阈值 (使用率)
    pub young_gen_threshold: f64,
    /// 对象晋升年龄
    pub promotion_age: usize,
    /// 并发 GC 线程数
    pub concurrent_gc_threads: usize,
    /// GC 间隔 (毫秒)
    pub gc_interval_ms: u64,
    /// 压缩阈值 (老年代使用率)
    pub compaction_threshold: f64,
}
impl Default for GCConfig {
    fn default() -> Self {
        Self {
            young_gen_size: 1024 * 1024,        // 1MB
            young_gen_max_size: 16 * 1024 * 1024, // 16MB
            old_gen_size: 64 * 1024 * 1024,     // 64MB
            old_gen_max_size: 1024 * 1024 * 1024, // 1GB
            young_gen_threshold: 0.8,           // 80%
            promotion_age: 3,                   // 3次年轻代回收
            concurrent_gc_threads: 4,
            gc_interval_ms: 100,                // 100ms
            compaction_threshold: 0.9,          // 90%
        }
    }
}
impl GenerationalGC {
    /// 创建新的分代 GC
    pub fn new(config: GCConfig) -> Self {
        let stop_flag: _ = Arc::new(Mutex::new(AtomicUsize::new(0)),;
        let stats: _ = Arc::new(Mutex::new(GCStats {)),
            young_gc_count: AtomicU64::new(0))
            old_gc_count: AtomicU64::new(0),
            total_collected_objects: AtomicU64::new(0),
            total_collected_bytes: AtomicU64::new(0),
            total_pause_time_ns: AtomicU64::new(0),
            max_pause_time_ns: AtomicU64::new(0),
            promoted_objects: AtomicU64::new(0),
            promotion_failures: AtomicU64::new(0),
        });
        let young_gen: _ = Arc::new(Mutex::new(YoungGeneration {)),
            live_objects: HashMap::new())
            free_space: config.young_gen_size,
            total_space: config.young_gen_size,
            created_at: Instant::now(),
            last_gc: Instant::now(),
        }));
        let old_gen: _ = Arc::new(Mutex::new(OldGeneration {)),
            live_objects: HashMap::new())
            total_space: config.old_gen_size,
            compaction_count: AtomicUsize::new(0),
            created_at: Instant::now(),
        }));
        // 启动 GC 线程
        let gc_thread: _ = Some(Self::start_gc_thread(
            Arc::clone(young_gen),
            Arc::clone(old_gen),
            Arc::clone(stats),
            Arc::clone(stop_flag),
            config.clone(),
        ));
        Self {
            young_gen,
            old_gen,
            stats,
            config,
            gc_thread,
            stop_flag,
        }
    }
    /// 分配对象
    pub fn allocate(&self, size: usize) -> Option<usize> {
        let address: _ = self.allocate_in_young_gen(size);
        if address.is_some() {
            // 记录分配统计
            self.stats.total_collected_objects.fetch_add(1, Ordering::Relaxed);
        }
        address
    }
    /// 在年轻代分配对象
    fn allocate_in_young_gen(&self, size: usize) -> Option<usize> {
        let mut young_gen = self.young_gen.write().unwrap();
        // 检查空间是否足够
        if young_gen.free_space >= size {
            let address: _ = self.generate_address();
            let now: _ = Instant::now();
            young_gen.live_objects.insert(address, ObjectInfo {
                address,
                size,
                created_at: now,
                last_accessed: now,
                age: 0,
                promotion_threshold: self.config.promotion_age,
            });
            young_gen.free_space -= size;
            Some(address)
        } else {
            // 空间不足,触发年轻代 GC
            drop(young_gen);
            self.trigger_young_gc();
            self.allocate_in_young_gen(size)
        }
    }
    /// 生成对象地址
    fn generate_address(&self) -> usize {
        // 简单的地址生成,实际实现中应该使用真实的内存地址
        let timestamp: _ = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_nanos() as usize;
        let random: _ = fastrand::usize(..);
        timestamp ^ random
    }
    /// 触发年轻代 GC
    fn trigger_young_gc(&self) {
        let start_time: _ = Instant::now();
        self.stats.young_gc_count.fetch_add(1, Ordering::Relaxed);
        let mut young_gen = self.young_gen.write().unwrap();
        // 标记-清除:标记存活对象,清除死亡对象
        let (live_objects, collected_bytes) = self.mark_and_sweep(&young_gen.live_objects);
        // 更新统计
        self.stats.total_collected_objects.fetch_add(
            (young_gen.live_objects.len() - live_objects.len()) as u64,
            Ordering::Relaxed
        );
        self.stats.total_collected_bytes.fetch_add(collected_bytes, Ordering::Relaxed);
        // 晋升存活对象
        let promoted_objects: _ = self.promote_objects(&mut young_gen, &live_objects);
        self.stats.promoted_objects.fetch_add(promoted_objects as u64, Ordering::Relaxed);
        young_gen.last_gc = Instant::now();
        // 计算停顿时间
        let pause_time: _ = start_time.elapsed();
        let pause_ns: _ = pause_time.as_nanos() as u64;
        self.stats.total_pause_time_ns.fetch_add(pause_ns, Ordering::Relaxed);
        // 更新最大停顿时间
        let current_max: _ = self.stats.max_pause_time_ns.load(Ordering::Relaxed);
        if pause_ns > current_max {
            self.stats.max_pause_time_ns.store(pause_ns, Ordering::Relaxed);
        }
    }
    /// 标记-清除算法
    fn mark_and_sweep(&self, objects: &HashMap<usize, ObjectInfo>) -> (HashMap<usize, ObjectInfo>, u64) {
        let mut live_objects = HashMap::new();
        let mut collected_bytes = 0u64;
        // 模拟标记过程:检查对象是否被引用
        for (addr, obj_info) in objects.iter() {
            if self.is_object_reachable(*addr) {
                // 对象存活,更新访问时间
                let mut updated_info = obj_info.clone();
                updated_info.last_accessed = Instant::now();
                updated_info.age += 1;
                live_objects.insert(*addr, updated_info);
            } else {
                // 对象死亡
                collected_bytes += obj_info.size as u64;
            }
        }
        (live_objects, collected_bytes)
    }
    /// 检查对象是否可达
    fn is_object_reachable(&self, _address: usize) -> bool {
        // 简化的可达性检查:实际实现中需要分析引用关系
        // 这里使用随机模拟,70% 的对象存活
        fastrand::f32() > 0.3
    }
    /// 晋升对象到老年代
    fn promote_objects(&self, young_gen: &mut YoungGeneration, live_objects: &HashMap<usize, ObjectInfo>) -> usize {
        let mut promoted_count = 0;
        let mut old_gen = self.old_gen.write().unwrap();
        for (addr, obj_info) in live_objects.iter() {
            // 检查是否应该晋升
            if obj_info.age >= obj_info.promotion_threshold {
                // 晋升到老年代
                old_gen.live_objects.insert(*addr, obj_info.clone());
                promoted_count += 1;
            }
        }
        // 从年轻代移除已晋升的对象
        young_gen.live_objects.retain(|addr, _| !old_gen.live_objects.contains_key(addr));
        promoted_count
    }
    /// 触发老年代 GC
    fn trigger_old_gc(&self) {
        let start_time: _ = Instant::now();
        self.stats.old_gc_count.fetch_add(1, Ordering::Relaxed);
        let mut old_gen = self.old_gen.write().unwrap();
        // 老年代使用率
        let usage_ratio: _ = old_gen.live_objects.values()
            .map(|obj| obj.size)
            .sum::<usize>() as f64 / old_gen.total_space as f64;
        // 如果超过压缩阈值,执行压缩
        if usage_ratio > self.config.compaction_threshold {
            self.compact_old_generation(&mut old_gen);
            old_gen.compaction_count.fetch_add(1, Ordering::Relaxed);
        }
        // 标记-清除老年代
        let (live_objects, collected_bytes) = self.mark_and_sweep(&old_gen.live_objects);
        old_gen.live_objects = live_objects;
        // 更新统计
        self.stats.total_collected_bytes.fetch_add(collected_bytes, Ordering::Relaxed);
        // 计算停顿时间
        let pause_time: _ = start_time.elapsed();
        let pause_ns: _ = pause_time.as_nanos() as u64;
        self.stats.total_pause_time_ns.fetch_add(pause_ns, Ordering::Relaxed);
    }
    /// 压缩老年代
    fn compact_old_generation(&self, old_gen: &mut OldGeneration) {
        // 简化的压缩实现:重建对象集合
        let objects: Vec<_> = old_gen.live_objects.values().cloned().collect();
        old_gen.live_objects.clear();
        for obj in objects {
            old_gen.live_objects.insert(obj.address, obj);
        }
    }
    /// 启动 GC 线程
    fn start_gc_thread(
        young_gen: Arc<RwLock<YoungGeneration>>,
        old_gen: Arc<RwLock<OldGeneration>>,
        stats: Arc<GCStats>,
        stop_flag: Arc<AtomicUsize>,
        config: GCConfig,
    ) -> thread::JoinHandle<()> {
        thread::spawn(move || {
            let mut last_gc = Instant::now();
            while stop_flag.load(Ordering::Relaxed) == 0 {
                let now: _ = Instant::now();
                // 检查是否需要 GC
                if now.duration_since(last_gc) > Duration::from_millis(config.gc_interval_ms) {
                    // 检查年轻代使用率
                    if let Ok(young_gen_guard) = young_gen.read() {
                        let usage_ratio: _ = (young_gen_guard.total_space - young_gen_guard.free_space) as f64
                            / young_gen_guard.total_space as f64;
                        if usage_ratio > config.young_gen_threshold {
                            drop(young_gen_guard);
                            // 触发年轻代 GC
                            Self::trigger_gc_internal(
                                Arc::clone(young_gen),
                                Arc::clone(old_gen),
                                Arc::clone(stats),
                                &config,
                            );
                        }
                    }
                    last_gc = now;
                }
                thread::sleep(Duration::from_millis(10));
            }
        })
    }
    /// 内部 GC 触发方法
    fn trigger_gc_internal(
        young_gen: Arc<RwLock<YoungGeneration>>,
        _old_gen: Arc<RwLock<OldGeneration>>,
        _stats: Arc<GCStats>,
        config: &GCConfig,
    ) {
        // 检查年轻代使用率
        if let Ok(young_gen) = young_gen.read() {
            let usage_ratio: _ = (young_gen.total_space - young_gen.free_space) as f64
                / young_gen.total_space as f64;
            if usage_ratio > config.young_gen_threshold {
                drop(young_gen);
                // 触发年轻代 GC
                // 注意:这里需要实际的 GC 实例来执行,实际实现中需要重构
            }
        }
    }
    /// 获取 GC 统计信息
    pub fn get_stats(&self) -> GCStatsSnapshot {
        let young_gen: _ = self.young_gen.read().unwrap();
        let old_gen: _ = self.old_gen.read().unwrap();
        GCStatsSnapshot {
            young_gc_count: self.stats.young_gc_count.load(Ordering::Relaxed),
            old_gc_count: self.stats.old_gc_count.load(Ordering::Relaxed),
            total_collected_objects: self.stats.total_collected_objects.load(Ordering::Relaxed),
            total_collected_bytes: self.stats.total_collected_bytes.load(Ordering::Relaxed),
            total_pause_time_ns: self.stats.total_pause_time_ns.load(Ordering::Relaxed),
            max_pause_time_ns: self.stats.max_pause_time_ns.load(Ordering::Relaxed),
            promoted_objects: self.stats.promoted_objects.load(Ordering::Relaxed),
            promotion_failures: self.stats.promotion_failures.load(Ordering::Relaxed),
            young_gen_usage_ratio: (young_gen.total_space - young_gen.free_space) as f64
                / young_gen.total_space as f64,
            old_gen_usage_ratio: old_gen.live_objects.values()
                .map(|obj| obj.size)
                .sum::<usize>() as f64 / old_gen.total_space as f64,
            avg_pause_time_ms: if self.stats.young_gc_count.load(Ordering::Relaxed) > 0 {
                self.stats.total_pause_time_ns.load(Ordering::Relaxed) as f64
                    / self.stats.young_gc_count.load(Ordering::Relaxed) as f64
                    / 1_000_000.0
            } else {
                0.0
            },
        }
    }
    /// 手动触发完整 GC
    pub fn trigger_full_gc(&self) {
        self.trigger_young_gc();
        self.trigger_old_gc();
    }
    /// 停止 GC
    pub fn stop(&mut self) {
        self.stop_flag.store(1, Ordering::Relaxed);
        if let Some(handle) = self.gc_thread.take() {
            handle.join().unwrap();
        }
    }
}
/// GC 统计快照
#[derive(Debug, Clone)]
pub struct GCStatsSnapshot {
    pub young_gc_count: u64,
    pub old_gc_count: u64,
    pub total_collected_objects: u64,
    pub total_collected_bytes: u64,
    pub total_pause_time_ns: u64,
    pub max_pause_time_ns: u64,
    pub promoted_objects: u64,
    pub promotion_failures: u64,
    pub young_gen_usage_ratio: f64,
    pub old_gen_usage_ratio: f64,
    pub avg_pause_time_ms: f64,
}
impl Drop for GenerationalGC {
    fn drop(&mut self) {
        self.stop();
    }
}