1#[allow(dead_code)]
8use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
9use std::marker::PhantomData;
10use std::ptr::NonNull;
11use std::sync::{Arc, Mutex, RwLock};
12use std::time::{Duration, Instant};
13
14pub struct GarbageCollectionEngine {
16 config: GCConfig,
18 stats: GCStats,
20 collectors: Vec<Box<dyn GarbageCollector>>,
22 memory_regions: HashMap<usize, MemoryRegion>,
24 reference_tracker: ReferenceTracker,
26 scheduler: GCScheduler,
28 performance_history: VecDeque<GCPerformance>,
30}
31
32#[derive(Debug, Clone)]
34pub struct GCConfig {
35 pub auto_gc: bool,
37 pub gc_threshold: f64,
39 pub max_pause_time: Duration,
41 pub enable_generational: bool,
43 pub enable_incremental: bool,
45 pub enable_concurrent: bool,
47 pub young_gen_ratio: f64,
49 pub survivor_ratio: f64,
51 pub tenuring_threshold: u32,
53 pub enable_stats: bool,
55 pub preferred_algorithm: GCAlgorithm,
57 pub parallel_gc: bool,
59 pub gc_threads: usize,
61}
62
63impl Default for GCConfig {
64 fn default() -> Self {
65 Self {
66 auto_gc: true,
67 gc_threshold: 0.8,
68 max_pause_time: Duration::from_millis(10),
69 enable_generational: true,
70 enable_incremental: true,
71 enable_concurrent: false,
72 young_gen_ratio: 0.3,
73 survivor_ratio: 0.1,
74 tenuring_threshold: 15,
75 enable_stats: true,
76 preferred_algorithm: GCAlgorithm::Generational,
77 parallel_gc: true,
78 gc_threads: 2,
79 }
80 }
81}
82
83#[derive(Debug, Clone, PartialEq)]
85pub enum GCAlgorithm {
86 MarkSweep,
88 Copying,
90 Generational,
92 Incremental,
94 Concurrent,
96 ReferenceCounting,
98 Adaptive,
100}
101
102#[derive(Debug, Clone, Default)]
104pub struct GCStats {
105 pub total_cycles: u64,
107 pub total_gc_time: Duration,
109 pub total_bytes_collected: u64,
111 pub total_objects_collected: u64,
113 pub average_pause_time: Duration,
115 pub max_pause_time: Duration,
117 pub gc_efficiency: f64,
119 pub young_gen_collections: u64,
121 pub old_gen_collections: u64,
123 pub promotion_rate: f64,
125 pub reclaim_rate: f64,
127 pub gc_overhead: f64,
129 pub last_gc_time: Option<Instant>,
131}
132
133#[derive(Debug, Clone)]
135pub struct MemoryRegion {
136 pub base_addr: usize,
138 pub size: usize,
140 pub generation: u32,
142 pub objects: HashMap<usize, ObjectMetadata>,
144 pub free_bitmap: Vec<u64>,
146 pub last_collection: Option<Instant>,
148 pub collection_count: u32,
150 pub utilization: f64,
152}
153
154#[derive(Debug, Clone)]
156pub struct ObjectMetadata {
157 pub address: usize,
159 pub size: usize,
161 pub type_id: u32,
163 pub ref_count: u32,
165 pub marked: bool,
167 pub age: u32,
169 pub last_access: Option<Instant>,
171 pub references: Vec<usize>,
173}
174
175pub struct ReferenceTracker {
177 reference_graph: HashMap<usize, HashSet<usize>>,
179 reverse_references: HashMap<usize, HashSet<usize>>,
181 root_references: HashSet<usize>,
183 write_barrier_log: VecDeque<WriteBarrierEntry>,
185}
186
187#[derive(Debug, Clone)]
189pub struct WriteBarrierEntry {
190 pub source: usize,
191 pub target: usize,
192 pub timestamp: Instant,
193}
194
195impl Default for ReferenceTracker {
196 fn default() -> Self {
197 Self::new()
198 }
199}
200
201impl ReferenceTracker {
202 pub fn new() -> Self {
203 Self {
204 reference_graph: HashMap::new(),
205 reverse_references: HashMap::new(),
206 root_references: HashSet::new(),
207 write_barrier_log: VecDeque::new(),
208 }
209 }
210
211 pub fn add_reference(&mut self, from: usize, to: usize) {
213 self.reference_graph.entry(from).or_default().insert(to);
214 self.reverse_references.entry(to).or_default().insert(from);
215 }
216
217 pub fn remove_reference(&mut self, from: usize, to: usize) {
219 if let Some(refs) = self.reference_graph.get_mut(&from) {
220 refs.remove(&to);
221 }
222 if let Some(refs) = self.reverse_references.get_mut(&to) {
223 refs.remove(&from);
224 }
225 }
226
227 pub fn add_root(&mut self, obj: usize) {
229 self.root_references.insert(obj);
230 }
231
232 pub fn remove_root(&mut self, obj: usize) {
234 self.root_references.remove(&obj);
235 }
236
237 pub fn get_reachable_objects(&self) -> HashSet<usize> {
239 let mut reachable = HashSet::new();
240 let mut work_list = VecDeque::new();
241
242 for &root in &self.root_references {
244 reachable.insert(root);
245 work_list.push_back(root);
246 }
247
248 while let Some(obj) = work_list.pop_front() {
250 if let Some(refs) = self.reference_graph.get(&obj) {
251 for &target in refs {
252 if reachable.insert(target) {
253 work_list.push_back(target);
254 }
255 }
256 }
257 }
258
259 reachable
260 }
261
262 pub fn write_barrier(&mut self, source: usize, target: usize) {
264 let entry = WriteBarrierEntry {
265 source,
266 target,
267 timestamp: Instant::now(),
268 };
269 self.write_barrier_log.push_back(entry);
270 }
271}
272
273pub struct GCScheduler {
275 scheduled_tasks: VecDeque<GCTask>,
277 current_task: Option<GCTask>,
279 timing_state: GCTimingState,
281 trigger_conditions: Vec<GCTrigger>,
283}
284
285#[derive(Debug, Clone)]
287pub struct GCTask {
288 pub id: u64,
289 pub algorithm: GCAlgorithm,
290 pub priority: GCPriority,
291 pub target_region: Option<usize>,
292 pub estimated_duration: Duration,
293 pub created_at: Instant,
294 pub deadline: Option<Instant>,
295}
296
297#[derive(Debug, Clone, PartialEq, Ord, PartialOrd, Eq)]
299pub enum GCPriority {
300 Low,
301 Normal,
302 High,
303 Critical,
304}
305
306#[derive(Debug, Clone)]
308pub struct GCTimingState {
309 pub last_young_gc: Option<Instant>,
310 pub last_old_gc: Option<Instant>,
311 pub gc_frequency: f64,
312 pub allocation_rate: f64,
313 pub memory_pressure: f64,
314}
315
316#[derive(Debug, Clone)]
318pub enum GCTrigger {
319 MemoryThreshold(f64),
320 TimeInterval(Duration),
321 AllocationCount(u64),
322 ExplicitRequest,
323 MemoryPressure,
324}
325
326pub trait GarbageCollector: Send + Sync {
328 fn name(&self) -> &str;
329 fn can_collect(&self, region: &MemoryRegion) -> bool;
330 fn estimate_collection_time(&self, region: &MemoryRegion) -> Duration;
331 fn collect(
332 &mut self,
333 region: &mut MemoryRegion,
334 tracker: &mut ReferenceTracker,
335 ) -> Result<GCResult, GCError>;
336 fn get_statistics(&self) -> GCCollectorStats;
337 fn configure(&mut self, config: &GCConfig);
338}
339
340#[derive(Debug, Clone)]
342pub struct GCResult {
343 pub bytes_collected: usize,
344 pub objects_collected: u32,
345 pub collection_time: Duration,
346 pub algorithm_used: GCAlgorithm,
347 pub regions_collected: Vec<usize>,
348 pub promotion_count: u32,
349 pub compaction_performed: bool,
350 pub efficiency_score: f64,
351}
352
353#[derive(Debug, Clone, Default)]
355pub struct GCCollectorStats {
356 pub collections: u64,
357 pub total_time: Duration,
358 pub total_bytes_collected: u64,
359 pub total_objects_collected: u64,
360 pub average_efficiency: f64,
361 pub success_rate: f64,
362}
363
364pub struct MarkSweepCollector {
366 stats: GCCollectorStats,
367 config: MarkSweepConfig,
368}
369
370#[derive(Debug, Clone)]
372pub struct MarkSweepConfig {
373 pub enable_compaction: bool,
374 pub mark_threshold: f64,
375 pub sweep_threshold: f64,
376 pub enable_parallel_marking: bool,
377 pub enable_parallel_sweeping: bool,
378}
379
380impl Default for MarkSweepConfig {
381 fn default() -> Self {
382 Self {
383 enable_compaction: true,
384 mark_threshold: 0.7,
385 sweep_threshold: 0.5,
386 enable_parallel_marking: true,
387 enable_parallel_sweeping: true,
388 }
389 }
390}
391
392impl MarkSweepCollector {
393 pub fn new(config: MarkSweepConfig) -> Self {
394 Self {
395 stats: GCCollectorStats::default(),
396 config,
397 }
398 }
399
400 fn mark_phase(&self, region: &mut MemoryRegion, tracker: &ReferenceTracker) -> HashSet<usize> {
401 let reachable = tracker.get_reachable_objects();
402
403 for (addr, obj) in region.objects.iter_mut() {
405 obj.marked = reachable.contains(addr);
406 }
407
408 reachable
409 }
410
411 fn sweep_phase(&self, region: &mut MemoryRegion) -> (usize, u32) {
412 let mut bytes_collected = 0;
413 let mut objects_collected = 0;
414 let mut objects_to_remove = Vec::new();
415
416 for (addr, obj) in ®ion.objects {
417 if !obj.marked {
418 bytes_collected += obj.size;
419 objects_collected += 1;
420 objects_to_remove.push(*addr);
421 }
422 }
423
424 for addr in objects_to_remove {
426 region.objects.remove(&addr);
427 }
428
429 for obj in region.objects.values_mut() {
431 obj.marked = false;
432 }
433
434 (bytes_collected, objects_collected)
435 }
436}
437
438impl GarbageCollector for MarkSweepCollector {
439 fn name(&self) -> &str {
440 "MarkSweep"
441 }
442
443 fn can_collect(&self, region: &MemoryRegion) -> bool {
444 !region.objects.is_empty() && region.utilization < self.config.mark_threshold
445 }
446
447 fn estimate_collection_time(&self, region: &MemoryRegion) -> Duration {
448 let object_count = region.objects.len();
449 let base_time = Duration::from_micros((object_count * 10) as u64);
450
451 if self.config.enable_compaction {
452 base_time + Duration::from_micros((object_count * 5) as u64)
453 } else {
454 base_time
455 }
456 }
457
458 fn collect(
459 &mut self,
460 region: &mut MemoryRegion,
461 tracker: &mut ReferenceTracker,
462 ) -> Result<GCResult, GCError> {
463 let start_time = Instant::now();
464
465 let reachable = self.mark_phase(region, tracker);
467
468 let (bytes_collected, objects_collected) = self.sweep_phase(region);
470
471 let collection_time = start_time.elapsed();
472
473 self.stats.collections += 1;
475 self.stats.total_time += collection_time;
476 self.stats.total_bytes_collected += bytes_collected as u64;
477 self.stats.total_objects_collected += objects_collected as u64;
478
479 let efficiency = if collection_time.as_millis() > 0 {
480 bytes_collected as f64 / collection_time.as_millis() as f64
481 } else {
482 0.0
483 };
484
485 self.stats.average_efficiency =
486 (self.stats.average_efficiency * (self.stats.collections - 1) as f64 + efficiency)
487 / self.stats.collections as f64;
488 self.stats.success_rate = 1.0; Ok(GCResult {
491 bytes_collected,
492 objects_collected,
493 collection_time,
494 algorithm_used: GCAlgorithm::MarkSweep,
495 regions_collected: vec![region.base_addr],
496 promotion_count: 0,
497 compaction_performed: self.config.enable_compaction,
498 efficiency_score: efficiency,
499 })
500 }
501
502 fn get_statistics(&self) -> GCCollectorStats {
503 self.stats.clone()
504 }
505
506 fn configure(&mut self, config: &GCConfig) {
507 self.config.enable_parallel_marking = config.parallel_gc;
509 self.config.enable_parallel_sweeping = config.parallel_gc;
510 }
511}
512
513pub struct GenerationalCollector {
515 stats: GCCollectorStats,
516 config: GenerationalConfig,
517 young_gen_collector: Box<dyn GarbageCollector>,
518 old_gen_collector: Box<dyn GarbageCollector>,
519}
520
521#[derive(Debug, Clone)]
523pub struct GenerationalConfig {
524 pub young_gen_threshold: usize,
525 pub promotion_age: u32,
526 pub minor_gc_frequency: u32,
527 pub major_gc_threshold: f64,
528 pub enable_remembered_set: bool,
529}
530
531impl Default for GenerationalConfig {
532 fn default() -> Self {
533 Self {
534 young_gen_threshold: 1024 * 1024, promotion_age: 3,
536 minor_gc_frequency: 10,
537 major_gc_threshold: 0.8,
538 enable_remembered_set: true,
539 }
540 }
541}
542
543impl GenerationalCollector {
544 pub fn new(config: GenerationalConfig) -> Self {
545 let young_collector = Box::new(MarkSweepCollector::new(MarkSweepConfig::default()));
546 let old_collector = Box::new(MarkSweepCollector::new(MarkSweepConfig {
547 enable_compaction: true,
548 ..MarkSweepConfig::default()
549 }));
550
551 Self {
552 stats: GCCollectorStats::default(),
553 config,
554 young_gen_collector: young_collector,
555 old_gen_collector: old_collector,
556 }
557 }
558
559 fn should_promote(&self, obj: &ObjectMetadata) -> bool {
560 obj.age >= self.config.promotion_age
561 }
562
563 fn promote_objects(&self, region: &mut MemoryRegion) -> u32 {
564 let mut promoted = 0;
565
566 for obj in region.objects.values_mut() {
567 if self.should_promote(obj) && region.generation == 0 {
568 promoted += 1;
569 }
571 }
572
573 promoted
574 }
575}
576
577impl GarbageCollector for GenerationalCollector {
578 fn name(&self) -> &str {
579 "Generational"
580 }
581
582 fn can_collect(&self, region: &MemoryRegion) -> bool {
583 !region.objects.is_empty()
584 }
585
586 fn estimate_collection_time(&self, region: &MemoryRegion) -> Duration {
587 if region.generation == 0 {
588 self.young_gen_collector.estimate_collection_time(region)
589 } else {
590 self.old_gen_collector.estimate_collection_time(region)
591 }
592 }
593
594 fn collect(
595 &mut self,
596 region: &mut MemoryRegion,
597 tracker: &mut ReferenceTracker,
598 ) -> Result<GCResult, GCError> {
599 let start_time = Instant::now();
600
601 let result = if region.generation == 0 {
602 self.young_gen_collector.collect(region, tracker)?
604 } else {
605 self.old_gen_collector.collect(region, tracker)?
607 };
608
609 let promotion_count = if region.generation == 0 {
611 self.promote_objects(region)
612 } else {
613 0
614 };
615
616 for obj in region.objects.values_mut() {
618 obj.age += 1;
619 }
620
621 let collection_time = start_time.elapsed();
622
623 self.stats.collections += 1;
625 self.stats.total_time += collection_time;
626 self.stats.total_bytes_collected += result.bytes_collected as u64;
627 self.stats.total_objects_collected += result.objects_collected as u64;
628
629 Ok(GCResult {
630 promotion_count,
631 ..result
632 })
633 }
634
635 fn get_statistics(&self) -> GCCollectorStats {
636 self.stats.clone()
637 }
638
639 fn configure(&mut self, config: &GCConfig) {
640 self.young_gen_collector.configure(config);
641 self.old_gen_collector.configure(config);
642 }
643}
644
645pub struct IncrementalCollector {
647 stats: GCCollectorStats,
648 config: IncrementalConfig,
649 current_phase: IncrementalPhase,
650 work_queue: VecDeque<IncrementalWork>,
651}
652
653#[derive(Debug, Clone)]
655pub struct IncrementalConfig {
656 pub time_slice: Duration,
657 pub work_unit_size: usize,
658 pub pause_threshold: Duration,
659 pub enable_write_barriers: bool,
660}
661
662impl Default for IncrementalConfig {
663 fn default() -> Self {
664 Self {
665 time_slice: Duration::from_millis(2),
666 work_unit_size: 100,
667 pause_threshold: Duration::from_millis(5),
668 enable_write_barriers: true,
669 }
670 }
671}
672
673#[derive(Debug, Clone, PartialEq)]
675pub enum IncrementalPhase {
676 Idle,
677 Marking,
678 Sweeping,
679 Compacting,
680 Finalizing,
681}
682
683#[derive(Debug, Clone)]
685pub struct IncrementalWork {
686 pub phase: IncrementalPhase,
687 pub region_addr: usize,
688 pub object_range: (usize, usize),
689 pub estimated_time: Duration,
690}
691
692impl IncrementalCollector {
693 pub fn new(config: IncrementalConfig) -> Self {
694 Self {
695 stats: GCCollectorStats::default(),
696 config,
697 current_phase: IncrementalPhase::Idle,
698 work_queue: VecDeque::new(),
699 }
700 }
701
702 fn schedule_incremental_work(&mut self, region: &MemoryRegion) {
703 let object_addrs: Vec<usize> = region.objects.keys().copied().collect();
704 let chunk_size = self.config.work_unit_size;
705
706 for chunk in object_addrs.chunks(chunk_size) {
708 if !chunk.is_empty() {
709 let work = IncrementalWork {
710 phase: IncrementalPhase::Marking,
711 region_addr: region.base_addr,
712 object_range: (chunk[0], chunk[chunk.len() - 1]),
713 estimated_time: Duration::from_micros(chunk.len() as u64 * 10),
714 };
715 self.work_queue.push_back(work);
716 }
717 }
718 }
719
720 fn perform_incremental_work(
721 &mut self,
722 region: &mut MemoryRegion,
723 tracker: &mut ReferenceTracker,
724 ) -> Option<GCResult> {
725 let time_budget = self.config.time_slice;
726 let start_time = Instant::now();
727 let mut work_done = false;
728
729 while start_time.elapsed() < time_budget {
730 if let Some(work) = self.work_queue.pop_front() {
731 match work.phase {
732 IncrementalPhase::Marking => {
733 let reachable = tracker.get_reachable_objects();
735 for addr in work.object_range.0..=work.object_range.1 {
736 if let Some(obj) = region.objects.get_mut(&addr) {
737 obj.marked = reachable.contains(&addr);
738 }
739 }
740 work_done = true;
741 }
742 IncrementalPhase::Sweeping => {
743 for addr in work.object_range.0..=work.object_range.1 {
745 if let Some(obj) = region.objects.get(&addr) {
746 if !obj.marked {
747 region.objects.remove(&addr);
748 }
749 }
750 }
751 work_done = true;
752 }
753 _ => {}
754 }
755 } else {
756 break;
757 }
758 }
759
760 if work_done && self.work_queue.is_empty() {
761 Some(GCResult {
763 bytes_collected: 0, objects_collected: 0, collection_time: start_time.elapsed(),
766 algorithm_used: GCAlgorithm::Incremental,
767 regions_collected: vec![region.base_addr],
768 promotion_count: 0,
769 compaction_performed: false,
770 efficiency_score: 0.0,
771 })
772 } else {
773 None
774 }
775 }
776}
777
778impl GarbageCollector for IncrementalCollector {
779 fn name(&self) -> &str {
780 "Incremental"
781 }
782
783 fn can_collect(&self, region: &MemoryRegion) -> bool {
784 !region.objects.is_empty()
785 }
786
787 fn estimate_collection_time(&self, region: &MemoryRegion) -> Duration {
788 let object_count = region.objects.len();
789 Duration::from_millis(
790 (object_count / self.config.work_unit_size) as u64
791 * self.config.time_slice.as_millis() as u64,
792 )
793 }
794
795 fn collect(
796 &mut self,
797 region: &mut MemoryRegion,
798 tracker: &mut ReferenceTracker,
799 ) -> Result<GCResult, GCError> {
800 if self.work_queue.is_empty() {
801 self.schedule_incremental_work(region);
802 }
803
804 if let Some(result) = self.perform_incremental_work(region, tracker) {
805 self.stats.collections += 1;
806 self.stats.total_time += result.collection_time;
807 Ok(result)
808 } else {
809 Err(GCError::CollectionIncomplete(
810 "Incremental collection in progress".to_string(),
811 ))
812 }
813 }
814
815 fn get_statistics(&self) -> GCCollectorStats {
816 self.stats.clone()
817 }
818
819 fn configure(&mut self, config: &GCConfig) {
820 self.config.time_slice = config.max_pause_time;
821 }
822}
823
824#[derive(Debug, Clone)]
826pub struct GCPerformance {
827 pub timestamp: Instant,
828 pub algorithm: GCAlgorithm,
829 pub collection_time: Duration,
830 pub bytes_collected: usize,
831 pub objects_collected: u32,
832 pub regions_affected: usize,
833 pub efficiency_score: f64,
834 pub memory_before: usize,
835 pub memory_after: usize,
836}
837
838impl GarbageCollectionEngine {
839 pub fn new(config: GCConfig) -> Self {
840 let mut collectors: Vec<Box<dyn GarbageCollector>> = Vec::new();
841
842 collectors.push(Box::new(
844 MarkSweepCollector::new(MarkSweepConfig::default()),
845 ));
846
847 if config.enable_generational {
848 collectors.push(Box::new(GenerationalCollector::new(
849 GenerationalConfig::default(),
850 )));
851 }
852
853 if config.enable_incremental {
854 collectors.push(Box::new(IncrementalCollector::new(
855 IncrementalConfig::default(),
856 )));
857 }
858
859 let gc_threshold = config.gc_threshold;
860 Self {
861 config,
862 stats: GCStats::default(),
863 collectors,
864 memory_regions: HashMap::new(),
865 reference_tracker: ReferenceTracker::new(),
866 scheduler: GCScheduler {
867 scheduled_tasks: VecDeque::new(),
868 current_task: None,
869 timing_state: GCTimingState {
870 last_young_gc: None,
871 last_old_gc: None,
872 gc_frequency: 0.0,
873 allocation_rate: 0.0,
874 memory_pressure: 0.0,
875 },
876 trigger_conditions: vec![
877 GCTrigger::MemoryThreshold(gc_threshold),
878 GCTrigger::TimeInterval(Duration::from_secs(30)),
879 ],
880 },
881 performance_history: VecDeque::with_capacity(1000),
882 }
883 }
884
885 pub fn register_region(&mut self, base_addr: usize, size: usize, generation: u32) {
887 let region = MemoryRegion {
888 base_addr,
889 size,
890 generation,
891 objects: HashMap::new(),
892 free_bitmap: vec![0; (size / 64) + 1],
893 last_collection: None,
894 collection_count: 0,
895 utilization: 0.0,
896 };
897
898 self.memory_regions.insert(base_addr, region);
899 }
900
901 pub fn track_object(
903 &mut self,
904 region_addr: usize,
905 obj_addr: usize,
906 size: usize,
907 type_id: u32,
908 ) -> Result<(), GCError> {
909 let region = self
910 .memory_regions
911 .get_mut(®ion_addr)
912 .ok_or_else(|| GCError::RegionNotFound("Region not registered".to_string()))?;
913
914 let metadata = ObjectMetadata {
915 address: obj_addr,
916 size,
917 type_id,
918 ref_count: 0,
919 marked: false,
920 age: 0,
921 last_access: Some(Instant::now()),
922 references: Vec::new(),
923 };
924
925 region.objects.insert(obj_addr, metadata);
926 Ok(())
927 }
928
929 pub fn should_collect(&mut self) -> bool {
931 if !self.config.auto_gc {
932 return false;
933 }
934
935 for trigger in &self.scheduler.trigger_conditions {
936 match trigger {
937 GCTrigger::MemoryThreshold(threshold) => {
938 let total_used = self.calculate_total_memory_usage();
939 let total_size = self.calculate_total_memory_size();
940 if total_size > 0 && (total_used as f64 / total_size as f64) > *threshold {
941 return true;
942 }
943 }
944 GCTrigger::TimeInterval(interval) => {
945 if let Some(last_gc) = self.stats.last_gc_time {
946 if last_gc.elapsed() > *interval {
947 return true;
948 }
949 } else {
950 return true; }
952 }
953 GCTrigger::MemoryPressure => {
954 if self.scheduler.timing_state.memory_pressure > 0.8 {
955 return true;
956 }
957 }
958 _ => {}
959 }
960 }
961
962 false
963 }
964
965 pub fn collect(&mut self) -> Result<Vec<GCResult>, GCError> {
967 let mut results = Vec::new();
968
969 let collector_indices: Result<Vec<(usize, usize)>, GCError> = self
971 .memory_regions
972 .iter()
973 .map(|(addr, region)| {
974 let collector_index = self.select_collector(region)?;
975 Ok((*addr, collector_index))
976 })
977 .collect();
978
979 let collector_indices = collector_indices?;
980
981 for (region_addr, collector_index) in collector_indices {
983 let utilization = {
985 let region = self
986 .memory_regions
987 .get(®ion_addr)
988 .ok_or_else(|| GCError::InvalidRegion("Region not found".to_string()))?;
989 self.calculate_region_utilization(region)
990 };
991
992 let region = self
993 .memory_regions
994 .get_mut(®ion_addr)
995 .ok_or_else(|| GCError::InvalidRegion("Region not found".to_string()))?;
996
997 let collector = &mut self.collectors[collector_index];
998
999 let result = collector.collect(region, &mut self.reference_tracker)?;
1001
1002 region.last_collection = Some(Instant::now());
1004 region.collection_count += 1;
1005 region.utilization = utilization;
1006
1007 self.stats.total_cycles += 1;
1009 self.stats.total_gc_time += result.collection_time;
1010 self.stats.total_bytes_collected += result.bytes_collected as u64;
1011 self.stats.total_objects_collected += result.objects_collected as u64;
1012
1013 let pause_time = result.collection_time;
1015 if pause_time > self.stats.max_pause_time {
1016 self.stats.max_pause_time = pause_time;
1017 }
1018
1019 let total_time = self.stats.average_pause_time.as_nanos() as u64
1020 * (self.stats.total_cycles - 1)
1021 + pause_time.as_nanos() as u64;
1022 self.stats.average_pause_time =
1023 Duration::from_nanos(total_time / self.stats.total_cycles);
1024
1025 let performance = GCPerformance {
1027 timestamp: Instant::now(),
1028 algorithm: result.algorithm_used.clone(),
1029 collection_time: result.collection_time,
1030 bytes_collected: result.bytes_collected,
1031 objects_collected: result.objects_collected,
1032 regions_affected: 1,
1033 efficiency_score: result.efficiency_score,
1034 memory_before: region.size, memory_after: region.size - result.bytes_collected,
1036 };
1037
1038 self.performance_history.push_back(performance);
1039 if self.performance_history.len() > 1000 {
1040 self.performance_history.pop_front();
1041 }
1042
1043 results.push(result);
1044 }
1045
1046 self.stats.last_gc_time = Some(Instant::now());
1047 Ok(results)
1048 }
1049
1050 fn select_collector(&self, region: &MemoryRegion) -> Result<usize, GCError> {
1051 for (i, collector) in self.collectors.iter().enumerate() {
1052 if collector.can_collect(region) {
1053 return Ok(i);
1054 }
1055 }
1056
1057 Err(GCError::NoSuitableCollector(
1058 "No collector available for region".to_string(),
1059 ))
1060 }
1061
1062 fn calculate_total_memory_usage(&self) -> usize {
1063 self.memory_regions
1064 .values()
1065 .map(|region| region.objects.values().map(|obj| obj.size).sum::<usize>())
1066 .sum()
1067 }
1068
1069 fn calculate_total_memory_size(&self) -> usize {
1070 self.memory_regions.values().map(|region| region.size).sum()
1071 }
1072
1073 fn calculate_region_utilization(&self, region: &MemoryRegion) -> f64 {
1074 let used_size: usize = region.objects.values().map(|obj| obj.size).sum();
1075 used_size as f64 / region.size as f64
1076 }
1077
1078 pub fn get_stats(&self) -> &GCStats {
1080 &self.stats
1081 }
1082
1083 pub fn get_performance_history(&self) -> &VecDeque<GCPerformance> {
1085 &self.performance_history
1086 }
1087
1088 pub fn get_collector_info(&self) -> Vec<(String, GCCollectorStats)> {
1090 self.collectors
1091 .iter()
1092 .map(|collector| (collector.name().to_string(), collector.get_statistics()))
1093 .collect()
1094 }
1095
1096 pub fn force_collect_region(&mut self, region_addr: usize) -> Result<GCResult, GCError> {
1098 let collector_index = {
1100 let region = self
1101 .memory_regions
1102 .get(®ion_addr)
1103 .ok_or_else(|| GCError::RegionNotFound("Region not found".to_string()))?;
1104 self.select_collector(region)?
1105 };
1106
1107 let region = self
1109 .memory_regions
1110 .get_mut(®ion_addr)
1111 .ok_or_else(|| GCError::RegionNotFound("Region not found".to_string()))?;
1112
1113 let collector = &mut self.collectors[collector_index];
1114 collector.collect(region, &mut self.reference_tracker)
1115 }
1116
1117 pub fn add_reference(&mut self, from: usize, to: usize) {
1119 self.reference_tracker.add_reference(from, to);
1120 }
1121
1122 pub fn remove_reference(&mut self, from: usize, to: usize) {
1124 self.reference_tracker.remove_reference(from, to);
1125 }
1126
1127 pub fn add_root_reference(&mut self, obj: usize) {
1129 self.reference_tracker.add_root(obj);
1130 }
1131
1132 pub fn remove_root_reference(&mut self, obj: usize) {
1134 self.reference_tracker.remove_root(obj);
1135 }
1136}
1137
1138#[derive(Debug, Clone)]
1140pub enum GCError {
1141 RegionNotFound(String),
1142 ObjectNotFound(String),
1143 CollectionFailed(String),
1144 CollectionIncomplete(String),
1145 NoSuitableCollector(String),
1146 ConfigurationError(String),
1147 InternalError(String),
1148 InvalidRegion(String),
1149}
1150
1151impl std::fmt::Display for GCError {
1152 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1153 match self {
1154 GCError::RegionNotFound(msg) => write!(f, "Region not found: {}", msg),
1155 GCError::ObjectNotFound(msg) => write!(f, "Object not found: {}", msg),
1156 GCError::CollectionFailed(msg) => write!(f, "Collection failed: {}", msg),
1157 GCError::CollectionIncomplete(msg) => write!(f, "Collection incomplete: {}", msg),
1158 GCError::NoSuitableCollector(msg) => write!(f, "No suitable collector: {}", msg),
1159 GCError::ConfigurationError(msg) => write!(f, "Configuration error: {}", msg),
1160 GCError::InternalError(msg) => write!(f, "Internal error: {}", msg),
1161 GCError::InvalidRegion(msg) => write!(f, "Invalid region: {}", msg),
1162 }
1163 }
1164}
1165
1166impl std::error::Error for GCError {}
1167
1168pub struct ThreadSafeGCEngine {
1170 engine: Arc<RwLock<GarbageCollectionEngine>>,
1171}
1172
1173impl ThreadSafeGCEngine {
1174 pub fn new(config: GCConfig) -> Self {
1175 Self {
1176 engine: Arc::new(RwLock::new(GarbageCollectionEngine::new(config))),
1177 }
1178 }
1179
1180 pub fn should_collect(&self) -> bool {
1181 let mut engine = self.engine.write().expect("lock poisoned");
1182 engine.should_collect()
1183 }
1184
1185 pub fn collect(&self) -> Result<Vec<GCResult>, GCError> {
1186 let mut engine = self.engine.write().expect("lock poisoned");
1187 engine.collect()
1188 }
1189
1190 pub fn get_stats(&self) -> GCStats {
1191 let engine = self.engine.read().expect("lock poisoned");
1192 engine.get_stats().clone()
1193 }
1194
1195 pub fn track_object(
1196 &self,
1197 region_addr: usize,
1198 obj_addr: usize,
1199 size: usize,
1200 type_id: u32,
1201 ) -> Result<(), GCError> {
1202 let mut engine = self.engine.write().expect("lock poisoned");
1203 engine.track_object(region_addr, obj_addr, size, type_id)
1204 }
1205}
1206
1207#[cfg(test)]
1208mod tests {
1209 use super::*;
1210
1211 #[test]
1212 fn test_gc_engine_creation() {
1213 let config = GCConfig::default();
1214 let engine = GarbageCollectionEngine::new(config);
1215 assert!(!engine.collectors.is_empty());
1216 }
1217
1218 #[test]
1219 fn test_region_registration() {
1220 let config = GCConfig::default();
1221 let mut engine = GarbageCollectionEngine::new(config);
1222
1223 engine.register_region(0x1000, 4096, 0);
1224 assert!(engine.memory_regions.contains_key(&0x1000));
1225 }
1226
1227 #[test]
1228 fn test_object_tracking() {
1229 let config = GCConfig::default();
1230 let mut engine = GarbageCollectionEngine::new(config);
1231
1232 engine.register_region(0x1000, 4096, 0);
1233 let result = engine.track_object(0x1000, 0x1100, 64, 1);
1234 assert!(result.is_ok());
1235 }
1236
1237 #[test]
1238 fn test_reference_tracking() {
1239 let mut tracker = ReferenceTracker::new();
1240
1241 tracker.add_root(100);
1242 tracker.add_reference(100, 200);
1243 tracker.add_reference(200, 300);
1244
1245 let reachable = tracker.get_reachable_objects();
1246 assert!(reachable.contains(&100));
1247 assert!(reachable.contains(&200));
1248 assert!(reachable.contains(&300));
1249 }
1250
1251 #[test]
1252 fn test_mark_sweep_collector() {
1253 let config = MarkSweepConfig::default();
1254 let collector = MarkSweepCollector::new(config);
1255
1256 assert_eq!(collector.name(), "MarkSweep");
1257 }
1258
1259 #[test]
1260 fn test_generational_collector() {
1261 let config = GenerationalConfig::default();
1262 let collector = GenerationalCollector::new(config);
1263
1264 assert_eq!(collector.name(), "Generational");
1265 }
1266
1267 #[test]
1268 fn test_incremental_collector() {
1269 let config = IncrementalConfig::default();
1270 let collector = IncrementalCollector::new(config);
1271
1272 assert_eq!(collector.name(), "Incremental");
1273 }
1274
1275 #[test]
1276 fn test_thread_safe_gc_engine() {
1277 let config = GCConfig::default();
1278 let engine = ThreadSafeGCEngine::new(config);
1279
1280 let stats = engine.get_stats();
1281 assert_eq!(stats.total_cycles, 0);
1282 }
1283}