pub struct GcHeap { /* private fields */ }Implementations§
Source§impl GcHeap
impl GcHeap
pub const DUMMY_DISPOSE_CALLBACK: fn(&GcHeap, &GcHead)
Sourcepub fn new(registry: &'static GcTypeRegistry) -> Self
pub fn new(registry: &'static GcTypeRegistry) -> Self
Create a new garbage collection heap with an explicit GC type registry
Examples found in repository?
More examples
51fn main() -> GcResult<()> {
52 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
53 let scope = heap.create_partition();
54
55 let static_ref = alloc_static(&mut heap, scope, 10)?;
56 let other_ref = alloc_other(&mut heap, scope, 20)?;
57
58 println!("Static node value: {}", static_ref._value);
59 println!("Other node value: {}", other_ref._value);
60
61 println!("gc_node_usage example verified");
62
63 Ok(())
64}38fn benchmark_object_sizes() {
39 let sizes = [10, 100, 500, 1000, 5000];
40
41 for &size in &sizes {
42 println!("\nTest object count: {}", size);
43
44 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
45 let partition = context.create_partition();
46
47 // Measure allocation performance
48 let alloc_start = Instant::now();
49 let mut objects = Vec::new();
50 for _i in 0..size {
51 let node = unsafe {
52 context.alloc_raw(
53 partition,
54 SimpleNode {
55 _data: vec![0u8; 100],
56 },
57 )
58 } // Each node 100 bytes
59 .unwrap();
60 objects.push(node);
61 }
62 let alloc_duration = alloc_start.elapsed();
63
64 println!(" Allocated {} objects in: {:?}", size, alloc_duration);
65 println!(
66 " Average allocation time per object: {:?}",
67 alloc_duration / size as u32
68 );
69
70 // Measure GC performance (all objects can be collected)
71 let gc_start = Instant::now();
72 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
73 let gc_duration = gc_start.elapsed();
74
75 println!(" GC回收 {} 字节耗时: {:?}", freed, gc_duration);
76 println!(
77 " Average collection time per byte: {:?}",
78 if freed > 0 {
79 gc_duration / freed as u32
80 } else {
81 Duration::from_nanos(0)
82 }
83 );
84 }
85}
86
87/// Test GC performance of complex object graphs
88fn benchmark_complex_graphs() {
89 let sizes = [100, 500, 1000];
90
91 for &size in &sizes {
92 println!("\nTest complex object graph size: {} nodes", size);
93
94 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
95 let partition = context.create_partition();
96
97 // Create complex object graph
98 let graph_start = Instant::now();
99 let mut nodes = Vec::new();
100
101 // Create all nodes
102 for _i in 0..size {
103 let node = unsafe {
104 context.alloc_raw(
105 partition,
106 GraphNode {
107 neighbors: Vec::new(),
108 },
109 )
110 }
111 .unwrap();
112 nodes.push(node);
113 }
114
115 // Establish complex dependencies
116 for i in 0..size {
117 {
118 // Each node points to subsequent nodes
119 for j in 1..=5 {
120 if i + j < size {
121 let n = nodes[i + j];
122 nodes[i].with_mut(&mut context, |node| node.neighbors.push(n));
123 }
124 }
125 // Every 10 nodes form a cycle
126 if i % 10 == 0 && i + 9 < size {
127 let n = nodes[i];
128 nodes[i + 9].with_mut(&mut context, |node| node.neighbors.push(n));
129 }
130 }
131 }
132 let graph_duration = graph_start.elapsed();
133
134 println!(" Built complex object graph in: {:?}", graph_duration);
135
136 // Measure GC performance
137 let gc_start = Instant::now();
138 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
139 let gc_duration = gc_start.elapsed();
140
141 println!(" GC回收 {} 字节耗时: {:?}", freed, gc_duration);
142 println!(
143 " Object graph complexity: average {} neighbors per node",
144 if size > 0 { (size * 5) / size } else { 0 }
145 );
146 }
147}
148
149/// Test memory usage efficiency
150fn benchmark_memory_efficiency() {
151 println!("\nTesting memory usage efficiency...");
152
153 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154 context.set_memory_limit(1024 * 1024); // 1MB global limit
155 let partition = context.create_partition();
156
157 // Allocate many small objects
158 let small_objects_count = 1000;
159 let mut small_objects = Vec::new();
160
161 for _i in 0..small_objects_count {
162 let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163 small_objects.push(obj);
164 }
165
166 if let Some(partition_info) = context.partition(partition) {
167 let used = partition_info.memory_used();
168 let limit = context.memory_limit();
169 let efficiency = if limit > 0 {
170 (used as f64 / limit as f64) * 100.0
171 } else {
172 0.0
173 };
174
175 println!(" After allocating {} small objects:", small_objects_count);
176 println!(
177 " Memory usage: {}/{} bytes ({:.1}%)",
178 used, limit, efficiency
179 );
180 println!(
181 " Average overhead per object: {} bytes",
182 if small_objects_count > 0 {
183 used / small_objects_count
184 } else {
185 0
186 }
187 );
188 }
189
190 // Collect all objects
191 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192 println!(" Collected all objects, freed {} bytes", freed);
193
194 // Verify complete memory collection
195 if let Some(partition_info) = context.partition(partition) {
196 let used_after = partition_info.memory_used();
197 println!(" Memory usage after collection: {} bytes", used_after);
198 println!(
199 " Memory collection rate: {:.1}%",
200 if freed > 0 {
201 (freed as f64 / (freed + used_after) as f64) * 100.0
202 } else {
203 0.0
204 }
205 );
206 }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211 println!("\nTesting automatic GC threshold performance...");
212
213 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214 context.set_memory_limit(2048); // 2KB global limit
215 let partition = context.create_partition();
216
217 // Set automatic GC threshold to 1.5KB
218 context.set_gc_threshold(1500);
219
220 // Allocate objects until automatic GC is triggered
221 let mut allocated_bytes = 0;
222 let mut object_count = 0;
223
224 println!(" Allocating objects until automatic GC is triggered...");
225
226 for _i in 0..100 {
227 // Try at most 100 times
228 // Allocate objects of about 100 bytes
229 let node = SimpleNode {
230 _data: vec![0u8; 100],
231 };
232 match unsafe { context.alloc_raw(partition, node) } {
233 Ok(_gc_ref) => {
234 allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235 object_count += 1;
236
237 // Check if approaching threshold
238 if let Some(partition_info) = context.partition(partition)
239 && partition_info.memory_used() >= 1500
240 {
241 println!(
242 " Reached automatic GC threshold, allocated {} objects",
243 object_count
244 );
245 println!(" Estimated allocated memory: {} bytes", allocated_bytes);
246 println!(
247 " Actual memory usage: {} bytes",
248 partition_info.memory_used()
249 );
250 break;
251 }
252 }
253 Err(_) => {
254 println!(" Allocation failed, automatic GC may have been triggered");
255 break;
256 }
257 }
258 }
259
260 // Manually trigger GC to see effect
261 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262 println!(" Manual GC freed {} bytes", freed);
263}34fn demonstrate_out_of_memory() -> GcResult<()> {
35 println!("1. Create limited memory partition...");
36
37 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
38 context.set_memory_limit(2048); // 2KB global limit
39 let partition_id = context.create_partition();
40
41 // Allocate first large object (1KB + header)
42 println!("2. Allocate first large object...");
43 let gc1: GcRef<LargeData> =
44 match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
45 Ok(gc_ref) => {
46 println!(" ✓ Successfully allocated first object (1KB)");
47 gc_ref
48 }
49 Err((error, _)) => {
50 println!(" ✗ First object allocation failed: {:?}", error);
51 return Ok(());
52 }
53 };
54
55 // Allocate second large object (1KB + header) - should exceed 2KB limit
56 println!("3. Try to allocate second large object...");
57 match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
58 Err((GcError::PartitionFull, _)) => {
59 println!(" ✓ Correctly detected partition full error");
60 }
61 Ok(_) => {
62 println!(" ✗ Expected partition full error, but allocation succeeded");
63 return Ok(());
64 }
65 Err((other_error, _)) => {
66 println!(
67 " ✗ Expected partition full error, but got: {:?}",
68 other_error
69 );
70 return Ok(());
71 }
72 }
73
74 // Clean up - through garbage collection instead of manual release
75 println!(" ✓ Automatic cleanup through GC");
76 context.garbage_collect(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
77
78 Ok(())
79}
80
81/// Demonstrate partition management errors
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83 println!("1. Test non-existent partition operations...");
84
85 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86 let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88 // Test allocating objects in non-existent partition
89 match unsafe {
90 context.alloc_raw(
91 invalid_partition,
92 TestData {
93 value: 42,
94 name: "test".to_string(),
95 },
96 )
97 } {
98 Err((GcError::PartitionNotFound, _)) => {
99 println!(" ✓ Allocating objects in non-existent partition returns correct error");
100 }
101 Ok(_) => {
102 println!(" ✗ Expected partition not found error, but allocation succeeded");
103 }
104 Err((other_error, _)) => {
105 println!(
106 " ✗ Expected partition not found error, but got: {:?}",
107 other_error
108 );
109 }
110 }
111
112 // Test getting non-existent partition information
113 let partition_info = context.partition(invalid_partition);
114 assert!(
115 partition_info.is_none(),
116 "Non-existent partition should return None"
117 );
118 println!(" ✓ Getting non-existent partition info returns None");
119
120 // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121 context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122 println!(" ✓ Removing non-existent partition silently fails");
123
124 println!("\n2. Test non-empty partition deletion...");
125 let partition_id = context.create_partition();
126
127 // Allocate objects in partition
128 let obj = unsafe {
129 context.alloc_raw(
130 partition_id,
131 TestData {
132 value: 1,
133 name: "obj".to_string(),
134 },
135 )
136 }
137 .unwrap();
138 let _ = obj;
139
140 // Try to delete non-empty partition (remove_partition will force cleanup)
141 context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142 println!(" ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144 Ok(())
145}
146
147/// Demonstrate GC threshold API errors
148fn demonstrate_gc_threshold_errors() -> GcResult<()> {
149 println!("1. Test GC threshold API...");
150
151 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
152 context.set_memory_limit(1024);
153 let _partition_id = context.create_partition();
154
155 // Test default values
156 println!("2. Test default threshold...");
157 assert_eq!(context.gc_threshold(), 0);
158 println!(" ✓ Default threshold is 0, automatic GC disabled");
159
160 // Test setting threshold
161 println!("3. Test setting threshold...");
162 context.set_gc_threshold(512);
163 assert_eq!(context.gc_threshold(), 512);
164 println!(" ✓ Successfully set threshold to 512, automatic GC enabled");
165
166 // Test setting threshold exceeding memory limit
167 println!("4. Test setting threshold exceeding memory limit...");
168 context.set_gc_threshold(2048);
169 // Since threshold exceeds memory limit, will be capped at 0.8x of limit (1024 * 8 / 10 = 819)
170 assert_eq!(context.gc_threshold(), 819);
171 println!(
172 " ✓ Setting threshold exceeding memory limit automatically adjusted to 0.8x of memory limit"
173 );
174
175 // Test disabling automatic GC
176 println!("5. Test disabling automatic GC...");
177 context.set_gc_threshold(0);
178 assert_eq!(context.gc_threshold(), 0);
179 println!(" ✓ Successfully disabled automatic GC, threshold set to 0");
180
181 Ok(())
182}49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 // Create garbage collection context
53 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 // Create two partitions
59 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 // Allocate objects in partition1
67 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 // Allocate objects in partition2
79 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 // Display partition status
88 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116 // No explicit `set_root` calls are needed for them.
117 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 // Manually trigger garbage collection for partition1
121 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 // Verify root objects are still valid
126 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 // Manually trigger garbage collection for partition2
131 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 // Verify partition2 root objects are still valid
136 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 // Trigger garbage collection for partition1 again to collect unreferenced objects
140 println!("\nTrigger garbage collection for partition1 again...");
141 // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142 // to test collection. For this example, we'll just collect other garbage.
143 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 // Verify remaining root objects are still valid
147 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 // Demonstrate automatic garbage collection
152 println!("\nDemonstrate automatic garbage collection...");
153
154 // Create a small partition to demonstrate automatic GC
155 let small_partition = heap.create_partition();
156
157 // Allocate multiple objects to fill partition
158 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 // Demonstrate weak references
166 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 // Upgrade weak reference
171 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 // Demonstrate complex types with GC references
184 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 // Establish references between nodes
191 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 // Trigger garbage collection, verify circular references are handled correctly
200 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 // Demonstrate partition deletion
205 println!("\nDemonstrate partition deletion:");
206
207 // Create an empty partition
208 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 // Delete empty partition
212 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 // Delete non-empty partition
216 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}pub const fn opaque(&self) -> *mut u8
pub const fn set_opaque(&mut self, opaque: *mut u8)
Sourcepub fn memory_limit(&self) -> usize
pub fn memory_limit(&self) -> usize
Examples found in repository?
150fn benchmark_memory_efficiency() {
151 println!("\nTesting memory usage efficiency...");
152
153 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154 context.set_memory_limit(1024 * 1024); // 1MB global limit
155 let partition = context.create_partition();
156
157 // Allocate many small objects
158 let small_objects_count = 1000;
159 let mut small_objects = Vec::new();
160
161 for _i in 0..small_objects_count {
162 let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163 small_objects.push(obj);
164 }
165
166 if let Some(partition_info) = context.partition(partition) {
167 let used = partition_info.memory_used();
168 let limit = context.memory_limit();
169 let efficiency = if limit > 0 {
170 (used as f64 / limit as f64) * 100.0
171 } else {
172 0.0
173 };
174
175 println!(" After allocating {} small objects:", small_objects_count);
176 println!(
177 " Memory usage: {}/{} bytes ({:.1}%)",
178 used, limit, efficiency
179 );
180 println!(
181 " Average overhead per object: {} bytes",
182 if small_objects_count > 0 {
183 used / small_objects_count
184 } else {
185 0
186 }
187 );
188 }
189
190 // Collect all objects
191 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192 println!(" Collected all objects, freed {} bytes", freed);
193
194 // Verify complete memory collection
195 if let Some(partition_info) = context.partition(partition) {
196 let used_after = partition_info.memory_used();
197 println!(" Memory usage after collection: {} bytes", used_after);
198 println!(
199 " Memory collection rate: {:.1}%",
200 if freed > 0 {
201 (freed as f64 / (freed + used_after) as f64) * 100.0
202 } else {
203 0.0
204 }
205 );
206 }
207}More examples
49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 // Create garbage collection context
53 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 // Create two partitions
59 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 // Allocate objects in partition1
67 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 // Allocate objects in partition2
79 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 // Display partition status
88 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116 // No explicit `set_root` calls are needed for them.
117 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 // Manually trigger garbage collection for partition1
121 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 // Verify root objects are still valid
126 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 // Manually trigger garbage collection for partition2
131 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 // Verify partition2 root objects are still valid
136 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 // Trigger garbage collection for partition1 again to collect unreferenced objects
140 println!("\nTrigger garbage collection for partition1 again...");
141 // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142 // to test collection. For this example, we'll just collect other garbage.
143 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 // Verify remaining root objects are still valid
147 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 // Demonstrate automatic garbage collection
152 println!("\nDemonstrate automatic garbage collection...");
153
154 // Create a small partition to demonstrate automatic GC
155 let small_partition = heap.create_partition();
156
157 // Allocate multiple objects to fill partition
158 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 // Demonstrate weak references
166 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 // Upgrade weak reference
171 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 // Demonstrate complex types with GC references
184 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 // Establish references between nodes
191 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 // Trigger garbage collection, verify circular references are handled correctly
200 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 // Demonstrate partition deletion
205 println!("\nDemonstrate partition deletion:");
206
207 // Create an empty partition
208 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 // Delete empty partition
212 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 // Delete non-empty partition
216 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}Sourcepub fn set_memory_limit(&mut self, limit: usize) -> usize
pub fn set_memory_limit(&mut self, limit: usize) -> usize
Examples found in repository?
34fn demonstrate_out_of_memory() -> GcResult<()> {
35 println!("1. Create limited memory partition...");
36
37 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
38 context.set_memory_limit(2048); // 2KB global limit
39 let partition_id = context.create_partition();
40
41 // Allocate first large object (1KB + header)
42 println!("2. Allocate first large object...");
43 let gc1: GcRef<LargeData> =
44 match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
45 Ok(gc_ref) => {
46 println!(" ✓ Successfully allocated first object (1KB)");
47 gc_ref
48 }
49 Err((error, _)) => {
50 println!(" ✗ First object allocation failed: {:?}", error);
51 return Ok(());
52 }
53 };
54
55 // Allocate second large object (1KB + header) - should exceed 2KB limit
56 println!("3. Try to allocate second large object...");
57 match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
58 Err((GcError::PartitionFull, _)) => {
59 println!(" ✓ Correctly detected partition full error");
60 }
61 Ok(_) => {
62 println!(" ✗ Expected partition full error, but allocation succeeded");
63 return Ok(());
64 }
65 Err((other_error, _)) => {
66 println!(
67 " ✗ Expected partition full error, but got: {:?}",
68 other_error
69 );
70 return Ok(());
71 }
72 }
73
74 // Clean up - through garbage collection instead of manual release
75 println!(" ✓ Automatic cleanup through GC");
76 context.garbage_collect(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
77
78 Ok(())
79}
80
81/// Demonstrate partition management errors
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83 println!("1. Test non-existent partition operations...");
84
85 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86 let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88 // Test allocating objects in non-existent partition
89 match unsafe {
90 context.alloc_raw(
91 invalid_partition,
92 TestData {
93 value: 42,
94 name: "test".to_string(),
95 },
96 )
97 } {
98 Err((GcError::PartitionNotFound, _)) => {
99 println!(" ✓ Allocating objects in non-existent partition returns correct error");
100 }
101 Ok(_) => {
102 println!(" ✗ Expected partition not found error, but allocation succeeded");
103 }
104 Err((other_error, _)) => {
105 println!(
106 " ✗ Expected partition not found error, but got: {:?}",
107 other_error
108 );
109 }
110 }
111
112 // Test getting non-existent partition information
113 let partition_info = context.partition(invalid_partition);
114 assert!(
115 partition_info.is_none(),
116 "Non-existent partition should return None"
117 );
118 println!(" ✓ Getting non-existent partition info returns None");
119
120 // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121 context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122 println!(" ✓ Removing non-existent partition silently fails");
123
124 println!("\n2. Test non-empty partition deletion...");
125 let partition_id = context.create_partition();
126
127 // Allocate objects in partition
128 let obj = unsafe {
129 context.alloc_raw(
130 partition_id,
131 TestData {
132 value: 1,
133 name: "obj".to_string(),
134 },
135 )
136 }
137 .unwrap();
138 let _ = obj;
139
140 // Try to delete non-empty partition (remove_partition will force cleanup)
141 context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142 println!(" ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144 Ok(())
145}
146
147/// Demonstrate GC threshold API errors
148fn demonstrate_gc_threshold_errors() -> GcResult<()> {
149 println!("1. Test GC threshold API...");
150
151 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
152 context.set_memory_limit(1024);
153 let _partition_id = context.create_partition();
154
155 // Test default values
156 println!("2. Test default threshold...");
157 assert_eq!(context.gc_threshold(), 0);
158 println!(" ✓ Default threshold is 0, automatic GC disabled");
159
160 // Test setting threshold
161 println!("3. Test setting threshold...");
162 context.set_gc_threshold(512);
163 assert_eq!(context.gc_threshold(), 512);
164 println!(" ✓ Successfully set threshold to 512, automatic GC enabled");
165
166 // Test setting threshold exceeding memory limit
167 println!("4. Test setting threshold exceeding memory limit...");
168 context.set_gc_threshold(2048);
169 // Since threshold exceeds memory limit, will be capped at 0.8x of limit (1024 * 8 / 10 = 819)
170 assert_eq!(context.gc_threshold(), 819);
171 println!(
172 " ✓ Setting threshold exceeding memory limit automatically adjusted to 0.8x of memory limit"
173 );
174
175 // Test disabling automatic GC
176 println!("5. Test disabling automatic GC...");
177 context.set_gc_threshold(0);
178 assert_eq!(context.gc_threshold(), 0);
179 println!(" ✓ Successfully disabled automatic GC, threshold set to 0");
180
181 Ok(())
182}More examples
150fn benchmark_memory_efficiency() {
151 println!("\nTesting memory usage efficiency...");
152
153 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154 context.set_memory_limit(1024 * 1024); // 1MB global limit
155 let partition = context.create_partition();
156
157 // Allocate many small objects
158 let small_objects_count = 1000;
159 let mut small_objects = Vec::new();
160
161 for _i in 0..small_objects_count {
162 let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163 small_objects.push(obj);
164 }
165
166 if let Some(partition_info) = context.partition(partition) {
167 let used = partition_info.memory_used();
168 let limit = context.memory_limit();
169 let efficiency = if limit > 0 {
170 (used as f64 / limit as f64) * 100.0
171 } else {
172 0.0
173 };
174
175 println!(" After allocating {} small objects:", small_objects_count);
176 println!(
177 " Memory usage: {}/{} bytes ({:.1}%)",
178 used, limit, efficiency
179 );
180 println!(
181 " Average overhead per object: {} bytes",
182 if small_objects_count > 0 {
183 used / small_objects_count
184 } else {
185 0
186 }
187 );
188 }
189
190 // Collect all objects
191 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192 println!(" Collected all objects, freed {} bytes", freed);
193
194 // Verify complete memory collection
195 if let Some(partition_info) = context.partition(partition) {
196 let used_after = partition_info.memory_used();
197 println!(" Memory usage after collection: {} bytes", used_after);
198 println!(
199 " Memory collection rate: {:.1}%",
200 if freed > 0 {
201 (freed as f64 / (freed + used_after) as f64) * 100.0
202 } else {
203 0.0
204 }
205 );
206 }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211 println!("\nTesting automatic GC threshold performance...");
212
213 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214 context.set_memory_limit(2048); // 2KB global limit
215 let partition = context.create_partition();
216
217 // Set automatic GC threshold to 1.5KB
218 context.set_gc_threshold(1500);
219
220 // Allocate objects until automatic GC is triggered
221 let mut allocated_bytes = 0;
222 let mut object_count = 0;
223
224 println!(" Allocating objects until automatic GC is triggered...");
225
226 for _i in 0..100 {
227 // Try at most 100 times
228 // Allocate objects of about 100 bytes
229 let node = SimpleNode {
230 _data: vec![0u8; 100],
231 };
232 match unsafe { context.alloc_raw(partition, node) } {
233 Ok(_gc_ref) => {
234 allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235 object_count += 1;
236
237 // Check if approaching threshold
238 if let Some(partition_info) = context.partition(partition)
239 && partition_info.memory_used() >= 1500
240 {
241 println!(
242 " Reached automatic GC threshold, allocated {} objects",
243 object_count
244 );
245 println!(" Estimated allocated memory: {} bytes", allocated_bytes);
246 println!(
247 " Actual memory usage: {} bytes",
248 partition_info.memory_used()
249 );
250 break;
251 }
252 }
253 Err(_) => {
254 println!(" Allocation failed, automatic GC may have been triggered");
255 break;
256 }
257 }
258 }
259
260 // Manually trigger GC to see effect
261 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262 println!(" Manual GC freed {} bytes", freed);
263}Sourcepub fn gc_threshold(&self) -> usize
pub fn gc_threshold(&self) -> usize
Examples found in repository?
148fn demonstrate_gc_threshold_errors() -> GcResult<()> {
149 println!("1. Test GC threshold API...");
150
151 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
152 context.set_memory_limit(1024);
153 let _partition_id = context.create_partition();
154
155 // Test default values
156 println!("2. Test default threshold...");
157 assert_eq!(context.gc_threshold(), 0);
158 println!(" ✓ Default threshold is 0, automatic GC disabled");
159
160 // Test setting threshold
161 println!("3. Test setting threshold...");
162 context.set_gc_threshold(512);
163 assert_eq!(context.gc_threshold(), 512);
164 println!(" ✓ Successfully set threshold to 512, automatic GC enabled");
165
166 // Test setting threshold exceeding memory limit
167 println!("4. Test setting threshold exceeding memory limit...");
168 context.set_gc_threshold(2048);
169 // Since threshold exceeds memory limit, will be capped at 0.8x of limit (1024 * 8 / 10 = 819)
170 assert_eq!(context.gc_threshold(), 819);
171 println!(
172 " ✓ Setting threshold exceeding memory limit automatically adjusted to 0.8x of memory limit"
173 );
174
175 // Test disabling automatic GC
176 println!("5. Test disabling automatic GC...");
177 context.set_gc_threshold(0);
178 assert_eq!(context.gc_threshold(), 0);
179 println!(" ✓ Successfully disabled automatic GC, threshold set to 0");
180
181 Ok(())
182}More examples
49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 // Create garbage collection context
53 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 // Create two partitions
59 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 // Allocate objects in partition1
67 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 // Allocate objects in partition2
79 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 // Display partition status
88 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116 // No explicit `set_root` calls are needed for them.
117 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 // Manually trigger garbage collection for partition1
121 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 // Verify root objects are still valid
126 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 // Manually trigger garbage collection for partition2
131 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 // Verify partition2 root objects are still valid
136 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 // Trigger garbage collection for partition1 again to collect unreferenced objects
140 println!("\nTrigger garbage collection for partition1 again...");
141 // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142 // to test collection. For this example, we'll just collect other garbage.
143 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 // Verify remaining root objects are still valid
147 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 // Demonstrate automatic garbage collection
152 println!("\nDemonstrate automatic garbage collection...");
153
154 // Create a small partition to demonstrate automatic GC
155 let small_partition = heap.create_partition();
156
157 // Allocate multiple objects to fill partition
158 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 // Demonstrate weak references
166 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 // Upgrade weak reference
171 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 // Demonstrate complex types with GC references
184 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 // Establish references between nodes
191 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 // Trigger garbage collection, verify circular references are handled correctly
200 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 // Demonstrate partition deletion
205 println!("\nDemonstrate partition deletion:");
206
207 // Create an empty partition
208 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 // Delete empty partition
212 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 // Delete non-empty partition
216 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}Sourcepub fn set_gc_threshold(&mut self, threshold: usize) -> usize
pub fn set_gc_threshold(&mut self, threshold: usize) -> usize
Examples found in repository?
148fn demonstrate_gc_threshold_errors() -> GcResult<()> {
149 println!("1. Test GC threshold API...");
150
151 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
152 context.set_memory_limit(1024);
153 let _partition_id = context.create_partition();
154
155 // Test default values
156 println!("2. Test default threshold...");
157 assert_eq!(context.gc_threshold(), 0);
158 println!(" ✓ Default threshold is 0, automatic GC disabled");
159
160 // Test setting threshold
161 println!("3. Test setting threshold...");
162 context.set_gc_threshold(512);
163 assert_eq!(context.gc_threshold(), 512);
164 println!(" ✓ Successfully set threshold to 512, automatic GC enabled");
165
166 // Test setting threshold exceeding memory limit
167 println!("4. Test setting threshold exceeding memory limit...");
168 context.set_gc_threshold(2048);
169 // Since threshold exceeds memory limit, will be capped at 0.8x of limit (1024 * 8 / 10 = 819)
170 assert_eq!(context.gc_threshold(), 819);
171 println!(
172 " ✓ Setting threshold exceeding memory limit automatically adjusted to 0.8x of memory limit"
173 );
174
175 // Test disabling automatic GC
176 println!("5. Test disabling automatic GC...");
177 context.set_gc_threshold(0);
178 assert_eq!(context.gc_threshold(), 0);
179 println!(" ✓ Successfully disabled automatic GC, threshold set to 0");
180
181 Ok(())
182}More examples
210fn benchmark_auto_gc_threshold() {
211 println!("\nTesting automatic GC threshold performance...");
212
213 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214 context.set_memory_limit(2048); // 2KB global limit
215 let partition = context.create_partition();
216
217 // Set automatic GC threshold to 1.5KB
218 context.set_gc_threshold(1500);
219
220 // Allocate objects until automatic GC is triggered
221 let mut allocated_bytes = 0;
222 let mut object_count = 0;
223
224 println!(" Allocating objects until automatic GC is triggered...");
225
226 for _i in 0..100 {
227 // Try at most 100 times
228 // Allocate objects of about 100 bytes
229 let node = SimpleNode {
230 _data: vec![0u8; 100],
231 };
232 match unsafe { context.alloc_raw(partition, node) } {
233 Ok(_gc_ref) => {
234 allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235 object_count += 1;
236
237 // Check if approaching threshold
238 if let Some(partition_info) = context.partition(partition)
239 && partition_info.memory_used() >= 1500
240 {
241 println!(
242 " Reached automatic GC threshold, allocated {} objects",
243 object_count
244 );
245 println!(" Estimated allocated memory: {} bytes", allocated_bytes);
246 println!(
247 " Actual memory usage: {} bytes",
248 partition_info.memory_used()
249 );
250 break;
251 }
252 }
253 Err(_) => {
254 println!(" Allocation failed, automatic GC may have been triggered");
255 break;
256 }
257 }
258 }
259
260 // Manually trigger GC to see effect
261 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262 println!(" Manual GC freed {} bytes", freed);
263}pub fn set_root_node(&mut self, node: NonNull<GcHead>)
Sourcepub fn contains(&self, node: NonNull<GcHead>) -> bool
pub fn contains(&self, node: NonNull<GcHead>) -> bool
Check if node was allocated in this heap
Examples found in repository?
274fn demonstrate_cross_context_detection() -> GcResult<()> {
275 println!("1. Create two independent heaps...");
276
277 let mut heap1 = new_heap();
278 let mut heap2 = new_heap();
279
280 let partition1 = heap1.create_partition();
281 let partition2 = heap2.create_partition();
282
283 let obj1 = unsafe {
284 heap1.alloc_root_raw(
285 partition1,
286 TestData {
287 value: 1,
288 name: "obj1".to_string(),
289 },
290 )
291 }
292 .map_err(|(e, _)| e)?;
293 let obj2 = unsafe {
294 heap2.alloc_raw(
295 partition2,
296 TestData {
297 value: 2,
298 name: "obj2".to_string(),
299 },
300 )
301 }
302 .map_err(|(e, _)| e)?;
303
304 println!("2. Test object source detection...");
305 assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
306 assert!(
307 !heap1.contains(obj2.node_ptr()),
308 "obj2 should not be from heap1"
309 );
310 assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
311 assert!(
312 !heap2.contains(obj1.node_ptr()),
313 "obj1 should not be from heap2"
314 );
315
316 println!(" ✓ Cross-context detection correct");
317
318 // Clean up
319 heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
320 heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
321
322 Ok(())
323}Sourcepub fn protect_node(&mut self, node: NonNull<GcHead>) -> bool
pub fn protect_node(&mut self, node: NonNull<GcHead>) -> bool
Protect node from being gc collected.
- if node is local or root, it’s protected, returns true
- otherwise if has current scope, add node to current scope and returns true
- can’t protect, returns false
Sourcepub fn protect_nodes_iter(
&mut self,
nodes: impl Iterator<Item = NonNull<GcHead>>,
)
pub fn protect_nodes_iter( &mut self, nodes: impl Iterator<Item = NonNull<GcHead>>, )
Protect nodes from being gc collected, for each node do following steps:
- if node is local or root, do nothing
- if has current scope, add node to current scope
- can’t protect, returns false
Sourcepub fn protect_nodes(&mut self, nodes: &[NonNull<GcHead>])
pub fn protect_nodes(&mut self, nodes: &[NonNull<GcHead>])
Protect nodes from being gc collected, for each node do following steps:
- if node is local or root, do nothing
- if has current scope, add node to current scope
- can’t protect, returns false
pub const fn memory_used(&self) -> usize
Source§impl GcHeap
impl GcHeap
pub fn add_gray_node(&mut self, node: NonNull<GcHead>)
pub fn mark_reset(&mut self, partition_id: GcPartitionId)
Sourcepub fn mark_prepare(&mut self, partition_id: GcPartitionId)
pub fn mark_prepare(&mut self, partition_id: GcPartitionId)
ensure marking is in progress, if marking is in progress, exit do nothing; if marking cycle is not started, start new cycle.
pub fn mark_grays( &mut self, partition_id: GcPartitionId, max_steps: usize, ) -> bool
pub fn mark(&mut self, partition_id: GcPartitionId, max_steps: usize) -> bool
Sourcepub fn sweep(
&mut self,
partition_id: GcPartitionId,
on_dispose: impl Fn(&GcHeap, &GcHead),
) -> usize
pub fn sweep( &mut self, partition_id: GcPartitionId, on_dispose: impl Fn(&GcHeap, &GcHead), ) -> usize
dispose white nodes in the partition
Sourcepub fn garbage_collect(
&mut self,
partition_id: GcPartitionId,
on_dispose: impl Fn(&GcHeap, &GcHead),
) -> usize
pub fn garbage_collect( &mut self, partition_id: GcPartitionId, on_dispose: impl Fn(&GcHeap, &GcHead), ) -> usize
Collect garbage on given partition, call notify with node BEFORE it is disposed.
Examples found in repository?
78fn demonstrate_weak_references(
79 heap: &mut GcHeap,
80 partition: gc_lite::GcPartitionId,
81) -> GcResult<()> {
82 println!("1. Create strong and weak references...");
83
84 let strong_ref =
85 unsafe { heap.alloc_root_raw(partition, MyString(String::from("Strong Reference Data"))) }
86 .map_err(|(err, _)| err)?;
87
88 let weak_ref = heap.downgrade(&strong_ref);
89 println!(" Created strong reference: {:?}", strong_ref);
90 println!(" Created weak reference: {:?}", weak_ref);
91
92 // Upgrade weak reference
93 println!("\n2. Upgrade weak reference...");
94 match weak_ref.upgrade(heap) {
95 Some(upgraded) => {
96 let data = upgraded.deref();
97 println!(" Weak reference upgrade successful: '{}'", data);
98 assert_eq!(data, "Strong Reference Data");
99 }
100 None => println!(" Weak reference upgrade failed"),
101 }
102
103 // Try upgrading after releasing strong reference
104 println!("\n3. Upgrade weak reference after releasing strong reference...");
105 heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
106
107 match weak_ref.upgrade(heap) {
108 Some(_) => {
109 println!(" Weak reference can still be upgraded (object may still be in memory)")
110 }
111 None => println!(" Weak reference upgrade failed (object has been collected)"),
112 }
113
114 Ok(())
115}
116
117/// Demonstrate circular reference handling
118fn demonstrate_cyclic_references(
119 heap: &mut GcHeap,
120 partition: gc_lite::GcPartitionId,
121) -> GcResult<()> {
122 println!("1. Create circular reference nodes...");
123
124 // Create two mutually referencing nodes
125 let mut node1 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node A")) }
126 .map_err(|(err, _)| err)?;
127 let mut node2 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node B")) }
128 .map_err(|(err, _)| err)?;
129
130 // Establish circular references
131 {
132 node1.with_mut(heap, |n| n.set_partner(node2));
133 node2.with_mut(heap, |n| n.set_partner(node1));
134 }
135
136 println!(" Created node1: {}", node1.deref());
137 println!(" Created node2: {}", node2.deref());
138
139 // Trigger garbage collection
140 println!("\n2. Trigger garbage collection (circular references still exist)...");
141 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
142 println!(" 回收了 {} 字节内存", freed);
143
144 // Verify circular references still exist
145 println!("\n3. Verify circular references...");
146 println!(" Node1's partner: {}", node1.get_partner_name());
147 println!(" Node2's partner: {}", node2.get_partner_name());
148
149 // Clear root object status, let circular references be collected
150 println!("\n4. Clear root object status and trigger GC again...");
151 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
152 println!(
153 " Freed {} bytes of memory (circular references correctly collected)",
154 freed
155 );
156
157 Ok(())
158}
159
160/// Demonstrate complex data structures
161fn demonstrate_complex_structures(
162 heap: &mut GcHeap,
163 partition: gc_lite::GcPartitionId,
164) -> GcResult<()> {
165 println!("1. Create complex data structures...");
166
167 // Create multiple nodes
168 let mut root_node =
169 unsafe { heap.alloc_root_raw(partition, TreeNode::new("Root")) }.map_err(|(err, _)| err)?;
170 let mut child1 =
171 unsafe { heap.alloc_raw(partition, TreeNode::new("Child 1")) }.map_err(|(err, _)| err)?;
172 let child2 =
173 unsafe { heap.alloc_raw(partition, TreeNode::new("Child 2")) }.map_err(|(err, _)| err)?;
174 let grandchild = unsafe { heap.alloc_raw(partition, TreeNode::new("Grandchild")) }
175 .map_err(|(err, _)| err)?;
176
177 // Build tree structure
178 {
179 root_node.with_mut(heap, |n| n.add_child(child1));
180 root_node.with_mut(heap, |n| n.add_child(child2));
181 child1.with_mut(heap, |n| n.add_child(grandchild));
182 }
183
184 // Create data container
185 let container = unsafe {
186 heap.alloc_root_raw(
187 partition,
188 DataContainer {
189 root: root_node,
190 metadata: vec![1, 2, 3],
191 optional_data: Some(child1),
192 },
193 )
194 }
195 .map_err(|(err, _)| err)?;
196
197 println!(" Created tree structure:");
198 println!(" Root -> Child 1 -> Grandchild");
199 println!(" Root -> Child 2");
200 println!(" Created data container");
201
202 // Trigger garbage collection
203 println!("\n2. Trigger garbage collection...");
204 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
205 println!(" 回收了 {} 字节内存", freed);
206
207 // Verify data structure integrity
208 println!("\n3. Verify data structure integrity...");
209 {
210 println!(" Container root node: {}", container.root.name);
211 println!(" Metadata length: {}", container.metadata.len());
212 println!(
213 " Optional data exists: {}",
214 container.optional_data.is_some()
215 );
216 }
217
218 Ok(())
219}
220
221/// Demonstrate reference recovery functionality
222fn demonstrate_reference_recovery(
223 heap: &mut GcHeap,
224 partition: gc_lite::GcPartitionId,
225) -> GcResult<()> {
226 println!("1. Create object and get reference...");
227
228 let original_ref = unsafe {
229 heap.alloc_raw(
230 partition,
231 TestData {
232 value: 42,
233 name: "test".to_string(),
234 },
235 )
236 }
237 .map_err(|(err, _)| err)?;
238
239 let data_ref = original_ref.deref();
240 println!(" Original reference: {:?}", original_ref);
241 println!(" Data: {:?}", data_ref);
242
243 // Recover GcRef from reference
244 println!("\n2. Recover GcRef from reference...");
245 let recovered_ref = GcRef::try_from_ref(heap, data_ref);
246
247 match recovered_ref {
248 Some(recovered) => {
249 println!(" Recovery successful: {:?}", recovered);
250 let recovered_data = recovered.deref();
251 println!(" Recovered data: {:?}", recovered_data);
252 println!(" Data equal: {}", data_ref == recovered_data);
253 println!(" Reference equal: {}", original_ref == recovered);
254 }
255 None => println!(" Recovery failed (possibly type registration issue)"),
256 }
257
258 // Test invalid reference recovery - create an object not in GC heap
259 println!("\n3. Test invalid reference recovery...");
260 let local_data = TestData {
261 value: 100,
262 name: "local".to_string(),
263 };
264 let invalid_result = GcRef::try_from_ref(heap, &local_data);
265 println!(
266 " Invalid reference recovery result: {:?} (should be None)",
267 invalid_result
268 );
269
270 Ok(())
271}
272
273/// Demonstrate cross-context detection
274fn demonstrate_cross_context_detection() -> GcResult<()> {
275 println!("1. Create two independent heaps...");
276
277 let mut heap1 = new_heap();
278 let mut heap2 = new_heap();
279
280 let partition1 = heap1.create_partition();
281 let partition2 = heap2.create_partition();
282
283 let obj1 = unsafe {
284 heap1.alloc_root_raw(
285 partition1,
286 TestData {
287 value: 1,
288 name: "obj1".to_string(),
289 },
290 )
291 }
292 .map_err(|(e, _)| e)?;
293 let obj2 = unsafe {
294 heap2.alloc_raw(
295 partition2,
296 TestData {
297 value: 2,
298 name: "obj2".to_string(),
299 },
300 )
301 }
302 .map_err(|(e, _)| e)?;
303
304 println!("2. Test object source detection...");
305 assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
306 assert!(
307 !heap1.contains(obj2.node_ptr()),
308 "obj2 should not be from heap1"
309 );
310 assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
311 assert!(
312 !heap2.contains(obj1.node_ptr()),
313 "obj1 should not be from heap2"
314 );
315
316 println!(" ✓ Cross-context detection correct");
317
318 // Clean up
319 heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
320 heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
321
322 Ok(())
323}More examples
38fn benchmark_object_sizes() {
39 let sizes = [10, 100, 500, 1000, 5000];
40
41 for &size in &sizes {
42 println!("\nTest object count: {}", size);
43
44 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
45 let partition = context.create_partition();
46
47 // Measure allocation performance
48 let alloc_start = Instant::now();
49 let mut objects = Vec::new();
50 for _i in 0..size {
51 let node = unsafe {
52 context.alloc_raw(
53 partition,
54 SimpleNode {
55 _data: vec![0u8; 100],
56 },
57 )
58 } // Each node 100 bytes
59 .unwrap();
60 objects.push(node);
61 }
62 let alloc_duration = alloc_start.elapsed();
63
64 println!(" Allocated {} objects in: {:?}", size, alloc_duration);
65 println!(
66 " Average allocation time per object: {:?}",
67 alloc_duration / size as u32
68 );
69
70 // Measure GC performance (all objects can be collected)
71 let gc_start = Instant::now();
72 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
73 let gc_duration = gc_start.elapsed();
74
75 println!(" GC回收 {} 字节耗时: {:?}", freed, gc_duration);
76 println!(
77 " Average collection time per byte: {:?}",
78 if freed > 0 {
79 gc_duration / freed as u32
80 } else {
81 Duration::from_nanos(0)
82 }
83 );
84 }
85}
86
87/// Test GC performance of complex object graphs
88fn benchmark_complex_graphs() {
89 let sizes = [100, 500, 1000];
90
91 for &size in &sizes {
92 println!("\nTest complex object graph size: {} nodes", size);
93
94 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
95 let partition = context.create_partition();
96
97 // Create complex object graph
98 let graph_start = Instant::now();
99 let mut nodes = Vec::new();
100
101 // Create all nodes
102 for _i in 0..size {
103 let node = unsafe {
104 context.alloc_raw(
105 partition,
106 GraphNode {
107 neighbors: Vec::new(),
108 },
109 )
110 }
111 .unwrap();
112 nodes.push(node);
113 }
114
115 // Establish complex dependencies
116 for i in 0..size {
117 {
118 // Each node points to subsequent nodes
119 for j in 1..=5 {
120 if i + j < size {
121 let n = nodes[i + j];
122 nodes[i].with_mut(&mut context, |node| node.neighbors.push(n));
123 }
124 }
125 // Every 10 nodes form a cycle
126 if i % 10 == 0 && i + 9 < size {
127 let n = nodes[i];
128 nodes[i + 9].with_mut(&mut context, |node| node.neighbors.push(n));
129 }
130 }
131 }
132 let graph_duration = graph_start.elapsed();
133
134 println!(" Built complex object graph in: {:?}", graph_duration);
135
136 // Measure GC performance
137 let gc_start = Instant::now();
138 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
139 let gc_duration = gc_start.elapsed();
140
141 println!(" GC回收 {} 字节耗时: {:?}", freed, gc_duration);
142 println!(
143 " Object graph complexity: average {} neighbors per node",
144 if size > 0 { (size * 5) / size } else { 0 }
145 );
146 }
147}
148
149/// Test memory usage efficiency
150fn benchmark_memory_efficiency() {
151 println!("\nTesting memory usage efficiency...");
152
153 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154 context.set_memory_limit(1024 * 1024); // 1MB global limit
155 let partition = context.create_partition();
156
157 // Allocate many small objects
158 let small_objects_count = 1000;
159 let mut small_objects = Vec::new();
160
161 for _i in 0..small_objects_count {
162 let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163 small_objects.push(obj);
164 }
165
166 if let Some(partition_info) = context.partition(partition) {
167 let used = partition_info.memory_used();
168 let limit = context.memory_limit();
169 let efficiency = if limit > 0 {
170 (used as f64 / limit as f64) * 100.0
171 } else {
172 0.0
173 };
174
175 println!(" After allocating {} small objects:", small_objects_count);
176 println!(
177 " Memory usage: {}/{} bytes ({:.1}%)",
178 used, limit, efficiency
179 );
180 println!(
181 " Average overhead per object: {} bytes",
182 if small_objects_count > 0 {
183 used / small_objects_count
184 } else {
185 0
186 }
187 );
188 }
189
190 // Collect all objects
191 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192 println!(" Collected all objects, freed {} bytes", freed);
193
194 // Verify complete memory collection
195 if let Some(partition_info) = context.partition(partition) {
196 let used_after = partition_info.memory_used();
197 println!(" Memory usage after collection: {} bytes", used_after);
198 println!(
199 " Memory collection rate: {:.1}%",
200 if freed > 0 {
201 (freed as f64 / (freed + used_after) as f64) * 100.0
202 } else {
203 0.0
204 }
205 );
206 }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211 println!("\nTesting automatic GC threshold performance...");
212
213 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214 context.set_memory_limit(2048); // 2KB global limit
215 let partition = context.create_partition();
216
217 // Set automatic GC threshold to 1.5KB
218 context.set_gc_threshold(1500);
219
220 // Allocate objects until automatic GC is triggered
221 let mut allocated_bytes = 0;
222 let mut object_count = 0;
223
224 println!(" Allocating objects until automatic GC is triggered...");
225
226 for _i in 0..100 {
227 // Try at most 100 times
228 // Allocate objects of about 100 bytes
229 let node = SimpleNode {
230 _data: vec![0u8; 100],
231 };
232 match unsafe { context.alloc_raw(partition, node) } {
233 Ok(_gc_ref) => {
234 allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235 object_count += 1;
236
237 // Check if approaching threshold
238 if let Some(partition_info) = context.partition(partition)
239 && partition_info.memory_used() >= 1500
240 {
241 println!(
242 " Reached automatic GC threshold, allocated {} objects",
243 object_count
244 );
245 println!(" Estimated allocated memory: {} bytes", allocated_bytes);
246 println!(
247 " Actual memory usage: {} bytes",
248 partition_info.memory_used()
249 );
250 break;
251 }
252 }
253 Err(_) => {
254 println!(" Allocation failed, automatic GC may have been triggered");
255 break;
256 }
257 }
258 }
259
260 // Manually trigger GC to see effect
261 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262 println!(" Manual GC freed {} bytes", freed);
263}34fn demonstrate_out_of_memory() -> GcResult<()> {
35 println!("1. Create limited memory partition...");
36
37 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
38 context.set_memory_limit(2048); // 2KB global limit
39 let partition_id = context.create_partition();
40
41 // Allocate first large object (1KB + header)
42 println!("2. Allocate first large object...");
43 let gc1: GcRef<LargeData> =
44 match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
45 Ok(gc_ref) => {
46 println!(" ✓ Successfully allocated first object (1KB)");
47 gc_ref
48 }
49 Err((error, _)) => {
50 println!(" ✗ First object allocation failed: {:?}", error);
51 return Ok(());
52 }
53 };
54
55 // Allocate second large object (1KB + header) - should exceed 2KB limit
56 println!("3. Try to allocate second large object...");
57 match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
58 Err((GcError::PartitionFull, _)) => {
59 println!(" ✓ Correctly detected partition full error");
60 }
61 Ok(_) => {
62 println!(" ✗ Expected partition full error, but allocation succeeded");
63 return Ok(());
64 }
65 Err((other_error, _)) => {
66 println!(
67 " ✗ Expected partition full error, but got: {:?}",
68 other_error
69 );
70 return Ok(());
71 }
72 }
73
74 // Clean up - through garbage collection instead of manual release
75 println!(" ✓ Automatic cleanup through GC");
76 context.garbage_collect(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
77
78 Ok(())
79}49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 // Create garbage collection context
53 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 // Create two partitions
59 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 // Allocate objects in partition1
67 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 // Allocate objects in partition2
79 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 // Display partition status
88 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116 // No explicit `set_root` calls are needed for them.
117 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 // Manually trigger garbage collection for partition1
121 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 // Verify root objects are still valid
126 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 // Manually trigger garbage collection for partition2
131 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 // Verify partition2 root objects are still valid
136 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 // Trigger garbage collection for partition1 again to collect unreferenced objects
140 println!("\nTrigger garbage collection for partition1 again...");
141 // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142 // to test collection. For this example, we'll just collect other garbage.
143 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 // Verify remaining root objects are still valid
147 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 // Demonstrate automatic garbage collection
152 println!("\nDemonstrate automatic garbage collection...");
153
154 // Create a small partition to demonstrate automatic GC
155 let small_partition = heap.create_partition();
156
157 // Allocate multiple objects to fill partition
158 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 // Demonstrate weak references
166 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 // Upgrade weak reference
171 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 // Demonstrate complex types with GC references
184 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 // Establish references between nodes
191 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 // Trigger garbage collection, verify circular references are handled correctly
200 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 // Demonstrate partition deletion
205 println!("\nDemonstrate partition deletion:");
206
207 // Create an empty partition
208 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 // Delete empty partition
212 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 // Delete non-empty partition
216 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}Source§impl GcHeap
impl GcHeap
Sourcepub unsafe fn alloc_raw<T: GcNode>(
&mut self,
partition_id: GcPartitionId,
payload: T,
) -> Result<GcRef<T>, (GcError, T)>
pub unsafe fn alloc_raw<T: GcNode>( &mut self, partition_id: GcPartitionId, payload: T, ) -> Result<GcRef<T>, (GcError, T)>
Allocate a typed gc node with payload data, do not put to any scope, even if the current scope is present.
§SAFETY
This function is unsafe because it directly manipulates raw pointers and memory allocation.
The caller must ensure that the partition_id is valid and that the returned GcRef is
properly managed to avoid memory leaks or use-after-free errors.
Examples found in repository?
38fn benchmark_object_sizes() {
39 let sizes = [10, 100, 500, 1000, 5000];
40
41 for &size in &sizes {
42 println!("\nTest object count: {}", size);
43
44 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
45 let partition = context.create_partition();
46
47 // Measure allocation performance
48 let alloc_start = Instant::now();
49 let mut objects = Vec::new();
50 for _i in 0..size {
51 let node = unsafe {
52 context.alloc_raw(
53 partition,
54 SimpleNode {
55 _data: vec![0u8; 100],
56 },
57 )
58 } // Each node 100 bytes
59 .unwrap();
60 objects.push(node);
61 }
62 let alloc_duration = alloc_start.elapsed();
63
64 println!(" Allocated {} objects in: {:?}", size, alloc_duration);
65 println!(
66 " Average allocation time per object: {:?}",
67 alloc_duration / size as u32
68 );
69
70 // Measure GC performance (all objects can be collected)
71 let gc_start = Instant::now();
72 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
73 let gc_duration = gc_start.elapsed();
74
75 println!(" GC回收 {} 字节耗时: {:?}", freed, gc_duration);
76 println!(
77 " Average collection time per byte: {:?}",
78 if freed > 0 {
79 gc_duration / freed as u32
80 } else {
81 Duration::from_nanos(0)
82 }
83 );
84 }
85}
86
87/// Test GC performance of complex object graphs
88fn benchmark_complex_graphs() {
89 let sizes = [100, 500, 1000];
90
91 for &size in &sizes {
92 println!("\nTest complex object graph size: {} nodes", size);
93
94 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
95 let partition = context.create_partition();
96
97 // Create complex object graph
98 let graph_start = Instant::now();
99 let mut nodes = Vec::new();
100
101 // Create all nodes
102 for _i in 0..size {
103 let node = unsafe {
104 context.alloc_raw(
105 partition,
106 GraphNode {
107 neighbors: Vec::new(),
108 },
109 )
110 }
111 .unwrap();
112 nodes.push(node);
113 }
114
115 // Establish complex dependencies
116 for i in 0..size {
117 {
118 // Each node points to subsequent nodes
119 for j in 1..=5 {
120 if i + j < size {
121 let n = nodes[i + j];
122 nodes[i].with_mut(&mut context, |node| node.neighbors.push(n));
123 }
124 }
125 // Every 10 nodes form a cycle
126 if i % 10 == 0 && i + 9 < size {
127 let n = nodes[i];
128 nodes[i + 9].with_mut(&mut context, |node| node.neighbors.push(n));
129 }
130 }
131 }
132 let graph_duration = graph_start.elapsed();
133
134 println!(" Built complex object graph in: {:?}", graph_duration);
135
136 // Measure GC performance
137 let gc_start = Instant::now();
138 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
139 let gc_duration = gc_start.elapsed();
140
141 println!(" GC回收 {} 字节耗时: {:?}", freed, gc_duration);
142 println!(
143 " Object graph complexity: average {} neighbors per node",
144 if size > 0 { (size * 5) / size } else { 0 }
145 );
146 }
147}
148
149/// Test memory usage efficiency
150fn benchmark_memory_efficiency() {
151 println!("\nTesting memory usage efficiency...");
152
153 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154 context.set_memory_limit(1024 * 1024); // 1MB global limit
155 let partition = context.create_partition();
156
157 // Allocate many small objects
158 let small_objects_count = 1000;
159 let mut small_objects = Vec::new();
160
161 for _i in 0..small_objects_count {
162 let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163 small_objects.push(obj);
164 }
165
166 if let Some(partition_info) = context.partition(partition) {
167 let used = partition_info.memory_used();
168 let limit = context.memory_limit();
169 let efficiency = if limit > 0 {
170 (used as f64 / limit as f64) * 100.0
171 } else {
172 0.0
173 };
174
175 println!(" After allocating {} small objects:", small_objects_count);
176 println!(
177 " Memory usage: {}/{} bytes ({:.1}%)",
178 used, limit, efficiency
179 );
180 println!(
181 " Average overhead per object: {} bytes",
182 if small_objects_count > 0 {
183 used / small_objects_count
184 } else {
185 0
186 }
187 );
188 }
189
190 // Collect all objects
191 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192 println!(" Collected all objects, freed {} bytes", freed);
193
194 // Verify complete memory collection
195 if let Some(partition_info) = context.partition(partition) {
196 let used_after = partition_info.memory_used();
197 println!(" Memory usage after collection: {} bytes", used_after);
198 println!(
199 " Memory collection rate: {:.1}%",
200 if freed > 0 {
201 (freed as f64 / (freed + used_after) as f64) * 100.0
202 } else {
203 0.0
204 }
205 );
206 }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211 println!("\nTesting automatic GC threshold performance...");
212
213 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214 context.set_memory_limit(2048); // 2KB global limit
215 let partition = context.create_partition();
216
217 // Set automatic GC threshold to 1.5KB
218 context.set_gc_threshold(1500);
219
220 // Allocate objects until automatic GC is triggered
221 let mut allocated_bytes = 0;
222 let mut object_count = 0;
223
224 println!(" Allocating objects until automatic GC is triggered...");
225
226 for _i in 0..100 {
227 // Try at most 100 times
228 // Allocate objects of about 100 bytes
229 let node = SimpleNode {
230 _data: vec![0u8; 100],
231 };
232 match unsafe { context.alloc_raw(partition, node) } {
233 Ok(_gc_ref) => {
234 allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235 object_count += 1;
236
237 // Check if approaching threshold
238 if let Some(partition_info) = context.partition(partition)
239 && partition_info.memory_used() >= 1500
240 {
241 println!(
242 " Reached automatic GC threshold, allocated {} objects",
243 object_count
244 );
245 println!(" Estimated allocated memory: {} bytes", allocated_bytes);
246 println!(
247 " Actual memory usage: {} bytes",
248 partition_info.memory_used()
249 );
250 break;
251 }
252 }
253 Err(_) => {
254 println!(" Allocation failed, automatic GC may have been triggered");
255 break;
256 }
257 }
258 }
259
260 // Manually trigger GC to see effect
261 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262 println!(" Manual GC freed {} bytes", freed);
263}More examples
34fn demonstrate_out_of_memory() -> GcResult<()> {
35 println!("1. Create limited memory partition...");
36
37 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
38 context.set_memory_limit(2048); // 2KB global limit
39 let partition_id = context.create_partition();
40
41 // Allocate first large object (1KB + header)
42 println!("2. Allocate first large object...");
43 let gc1: GcRef<LargeData> =
44 match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
45 Ok(gc_ref) => {
46 println!(" ✓ Successfully allocated first object (1KB)");
47 gc_ref
48 }
49 Err((error, _)) => {
50 println!(" ✗ First object allocation failed: {:?}", error);
51 return Ok(());
52 }
53 };
54
55 // Allocate second large object (1KB + header) - should exceed 2KB limit
56 println!("3. Try to allocate second large object...");
57 match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
58 Err((GcError::PartitionFull, _)) => {
59 println!(" ✓ Correctly detected partition full error");
60 }
61 Ok(_) => {
62 println!(" ✗ Expected partition full error, but allocation succeeded");
63 return Ok(());
64 }
65 Err((other_error, _)) => {
66 println!(
67 " ✗ Expected partition full error, but got: {:?}",
68 other_error
69 );
70 return Ok(());
71 }
72 }
73
74 // Clean up - through garbage collection instead of manual release
75 println!(" ✓ Automatic cleanup through GC");
76 context.garbage_collect(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
77
78 Ok(())
79}
80
81/// Demonstrate partition management errors
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83 println!("1. Test non-existent partition operations...");
84
85 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86 let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88 // Test allocating objects in non-existent partition
89 match unsafe {
90 context.alloc_raw(
91 invalid_partition,
92 TestData {
93 value: 42,
94 name: "test".to_string(),
95 },
96 )
97 } {
98 Err((GcError::PartitionNotFound, _)) => {
99 println!(" ✓ Allocating objects in non-existent partition returns correct error");
100 }
101 Ok(_) => {
102 println!(" ✗ Expected partition not found error, but allocation succeeded");
103 }
104 Err((other_error, _)) => {
105 println!(
106 " ✗ Expected partition not found error, but got: {:?}",
107 other_error
108 );
109 }
110 }
111
112 // Test getting non-existent partition information
113 let partition_info = context.partition(invalid_partition);
114 assert!(
115 partition_info.is_none(),
116 "Non-existent partition should return None"
117 );
118 println!(" ✓ Getting non-existent partition info returns None");
119
120 // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121 context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122 println!(" ✓ Removing non-existent partition silently fails");
123
124 println!("\n2. Test non-empty partition deletion...");
125 let partition_id = context.create_partition();
126
127 // Allocate objects in partition
128 let obj = unsafe {
129 context.alloc_raw(
130 partition_id,
131 TestData {
132 value: 1,
133 name: "obj".to_string(),
134 },
135 )
136 }
137 .unwrap();
138 let _ = obj;
139
140 // Try to delete non-empty partition (remove_partition will force cleanup)
141 context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142 println!(" ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144 Ok(())
145}161fn demonstrate_complex_structures(
162 heap: &mut GcHeap,
163 partition: gc_lite::GcPartitionId,
164) -> GcResult<()> {
165 println!("1. Create complex data structures...");
166
167 // Create multiple nodes
168 let mut root_node =
169 unsafe { heap.alloc_root_raw(partition, TreeNode::new("Root")) }.map_err(|(err, _)| err)?;
170 let mut child1 =
171 unsafe { heap.alloc_raw(partition, TreeNode::new("Child 1")) }.map_err(|(err, _)| err)?;
172 let child2 =
173 unsafe { heap.alloc_raw(partition, TreeNode::new("Child 2")) }.map_err(|(err, _)| err)?;
174 let grandchild = unsafe { heap.alloc_raw(partition, TreeNode::new("Grandchild")) }
175 .map_err(|(err, _)| err)?;
176
177 // Build tree structure
178 {
179 root_node.with_mut(heap, |n| n.add_child(child1));
180 root_node.with_mut(heap, |n| n.add_child(child2));
181 child1.with_mut(heap, |n| n.add_child(grandchild));
182 }
183
184 // Create data container
185 let container = unsafe {
186 heap.alloc_root_raw(
187 partition,
188 DataContainer {
189 root: root_node,
190 metadata: vec![1, 2, 3],
191 optional_data: Some(child1),
192 },
193 )
194 }
195 .map_err(|(err, _)| err)?;
196
197 println!(" Created tree structure:");
198 println!(" Root -> Child 1 -> Grandchild");
199 println!(" Root -> Child 2");
200 println!(" Created data container");
201
202 // Trigger garbage collection
203 println!("\n2. Trigger garbage collection...");
204 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
205 println!(" 回收了 {} 字节内存", freed);
206
207 // Verify data structure integrity
208 println!("\n3. Verify data structure integrity...");
209 {
210 println!(" Container root node: {}", container.root.name);
211 println!(" Metadata length: {}", container.metadata.len());
212 println!(
213 " Optional data exists: {}",
214 container.optional_data.is_some()
215 );
216 }
217
218 Ok(())
219}
220
221/// Demonstrate reference recovery functionality
222fn demonstrate_reference_recovery(
223 heap: &mut GcHeap,
224 partition: gc_lite::GcPartitionId,
225) -> GcResult<()> {
226 println!("1. Create object and get reference...");
227
228 let original_ref = unsafe {
229 heap.alloc_raw(
230 partition,
231 TestData {
232 value: 42,
233 name: "test".to_string(),
234 },
235 )
236 }
237 .map_err(|(err, _)| err)?;
238
239 let data_ref = original_ref.deref();
240 println!(" Original reference: {:?}", original_ref);
241 println!(" Data: {:?}", data_ref);
242
243 // Recover GcRef from reference
244 println!("\n2. Recover GcRef from reference...");
245 let recovered_ref = GcRef::try_from_ref(heap, data_ref);
246
247 match recovered_ref {
248 Some(recovered) => {
249 println!(" Recovery successful: {:?}", recovered);
250 let recovered_data = recovered.deref();
251 println!(" Recovered data: {:?}", recovered_data);
252 println!(" Data equal: {}", data_ref == recovered_data);
253 println!(" Reference equal: {}", original_ref == recovered);
254 }
255 None => println!(" Recovery failed (possibly type registration issue)"),
256 }
257
258 // Test invalid reference recovery - create an object not in GC heap
259 println!("\n3. Test invalid reference recovery...");
260 let local_data = TestData {
261 value: 100,
262 name: "local".to_string(),
263 };
264 let invalid_result = GcRef::try_from_ref(heap, &local_data);
265 println!(
266 " Invalid reference recovery result: {:?} (should be None)",
267 invalid_result
268 );
269
270 Ok(())
271}
272
273/// Demonstrate cross-context detection
274fn demonstrate_cross_context_detection() -> GcResult<()> {
275 println!("1. Create two independent heaps...");
276
277 let mut heap1 = new_heap();
278 let mut heap2 = new_heap();
279
280 let partition1 = heap1.create_partition();
281 let partition2 = heap2.create_partition();
282
283 let obj1 = unsafe {
284 heap1.alloc_root_raw(
285 partition1,
286 TestData {
287 value: 1,
288 name: "obj1".to_string(),
289 },
290 )
291 }
292 .map_err(|(e, _)| e)?;
293 let obj2 = unsafe {
294 heap2.alloc_raw(
295 partition2,
296 TestData {
297 value: 2,
298 name: "obj2".to_string(),
299 },
300 )
301 }
302 .map_err(|(e, _)| e)?;
303
304 println!("2. Test object source detection...");
305 assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
306 assert!(
307 !heap1.contains(obj2.node_ptr()),
308 "obj2 should not be from heap1"
309 );
310 assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
311 assert!(
312 !heap2.contains(obj1.node_ptr()),
313 "obj1 should not be from heap2"
314 );
315
316 println!(" ✓ Cross-context detection correct");
317
318 // Clean up
319 heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
320 heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
321
322 Ok(())
323}49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 // Create garbage collection context
53 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 // Create two partitions
59 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 // Allocate objects in partition1
67 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 // Allocate objects in partition2
79 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 // Display partition status
88 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116 // No explicit `set_root` calls are needed for them.
117 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 // Manually trigger garbage collection for partition1
121 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 // Verify root objects are still valid
126 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 // Manually trigger garbage collection for partition2
131 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 // Verify partition2 root objects are still valid
136 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 // Trigger garbage collection for partition1 again to collect unreferenced objects
140 println!("\nTrigger garbage collection for partition1 again...");
141 // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142 // to test collection. For this example, we'll just collect other garbage.
143 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 // Verify remaining root objects are still valid
147 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 // Demonstrate automatic garbage collection
152 println!("\nDemonstrate automatic garbage collection...");
153
154 // Create a small partition to demonstrate automatic GC
155 let small_partition = heap.create_partition();
156
157 // Allocate multiple objects to fill partition
158 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 // Demonstrate weak references
166 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 // Upgrade weak reference
171 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 // Demonstrate complex types with GC references
184 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 // Establish references between nodes
191 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 // Trigger garbage collection, verify circular references are handled correctly
200 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 // Demonstrate partition deletion
205 println!("\nDemonstrate partition deletion:");
206
207 // Create an empty partition
208 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 // Delete empty partition
212 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 // Delete non-empty partition
216 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}Sourcepub unsafe fn alloc_root_raw<T: GcNode>(
&mut self,
partition_id: GcPartitionId,
payload: T,
) -> Result<GcRef<T>, (GcError, T)>
pub unsafe fn alloc_root_raw<T: GcNode>( &mut self, partition_id: GcPartitionId, payload: T, ) -> Result<GcRef<T>, (GcError, T)>
§SAFETY
This function is unsafe because it directly manipulates raw pointers and memory allocation.
The caller must ensure that the partition_id is valid and that the returned GcRef is
properly managed to avoid memory leaks or use-after-free errors.
Examples found in repository?
78fn demonstrate_weak_references(
79 heap: &mut GcHeap,
80 partition: gc_lite::GcPartitionId,
81) -> GcResult<()> {
82 println!("1. Create strong and weak references...");
83
84 let strong_ref =
85 unsafe { heap.alloc_root_raw(partition, MyString(String::from("Strong Reference Data"))) }
86 .map_err(|(err, _)| err)?;
87
88 let weak_ref = heap.downgrade(&strong_ref);
89 println!(" Created strong reference: {:?}", strong_ref);
90 println!(" Created weak reference: {:?}", weak_ref);
91
92 // Upgrade weak reference
93 println!("\n2. Upgrade weak reference...");
94 match weak_ref.upgrade(heap) {
95 Some(upgraded) => {
96 let data = upgraded.deref();
97 println!(" Weak reference upgrade successful: '{}'", data);
98 assert_eq!(data, "Strong Reference Data");
99 }
100 None => println!(" Weak reference upgrade failed"),
101 }
102
103 // Try upgrading after releasing strong reference
104 println!("\n3. Upgrade weak reference after releasing strong reference...");
105 heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
106
107 match weak_ref.upgrade(heap) {
108 Some(_) => {
109 println!(" Weak reference can still be upgraded (object may still be in memory)")
110 }
111 None => println!(" Weak reference upgrade failed (object has been collected)"),
112 }
113
114 Ok(())
115}
116
117/// Demonstrate circular reference handling
118fn demonstrate_cyclic_references(
119 heap: &mut GcHeap,
120 partition: gc_lite::GcPartitionId,
121) -> GcResult<()> {
122 println!("1. Create circular reference nodes...");
123
124 // Create two mutually referencing nodes
125 let mut node1 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node A")) }
126 .map_err(|(err, _)| err)?;
127 let mut node2 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node B")) }
128 .map_err(|(err, _)| err)?;
129
130 // Establish circular references
131 {
132 node1.with_mut(heap, |n| n.set_partner(node2));
133 node2.with_mut(heap, |n| n.set_partner(node1));
134 }
135
136 println!(" Created node1: {}", node1.deref());
137 println!(" Created node2: {}", node2.deref());
138
139 // Trigger garbage collection
140 println!("\n2. Trigger garbage collection (circular references still exist)...");
141 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
142 println!(" 回收了 {} 字节内存", freed);
143
144 // Verify circular references still exist
145 println!("\n3. Verify circular references...");
146 println!(" Node1's partner: {}", node1.get_partner_name());
147 println!(" Node2's partner: {}", node2.get_partner_name());
148
149 // Clear root object status, let circular references be collected
150 println!("\n4. Clear root object status and trigger GC again...");
151 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
152 println!(
153 " Freed {} bytes of memory (circular references correctly collected)",
154 freed
155 );
156
157 Ok(())
158}
159
160/// Demonstrate complex data structures
161fn demonstrate_complex_structures(
162 heap: &mut GcHeap,
163 partition: gc_lite::GcPartitionId,
164) -> GcResult<()> {
165 println!("1. Create complex data structures...");
166
167 // Create multiple nodes
168 let mut root_node =
169 unsafe { heap.alloc_root_raw(partition, TreeNode::new("Root")) }.map_err(|(err, _)| err)?;
170 let mut child1 =
171 unsafe { heap.alloc_raw(partition, TreeNode::new("Child 1")) }.map_err(|(err, _)| err)?;
172 let child2 =
173 unsafe { heap.alloc_raw(partition, TreeNode::new("Child 2")) }.map_err(|(err, _)| err)?;
174 let grandchild = unsafe { heap.alloc_raw(partition, TreeNode::new("Grandchild")) }
175 .map_err(|(err, _)| err)?;
176
177 // Build tree structure
178 {
179 root_node.with_mut(heap, |n| n.add_child(child1));
180 root_node.with_mut(heap, |n| n.add_child(child2));
181 child1.with_mut(heap, |n| n.add_child(grandchild));
182 }
183
184 // Create data container
185 let container = unsafe {
186 heap.alloc_root_raw(
187 partition,
188 DataContainer {
189 root: root_node,
190 metadata: vec![1, 2, 3],
191 optional_data: Some(child1),
192 },
193 )
194 }
195 .map_err(|(err, _)| err)?;
196
197 println!(" Created tree structure:");
198 println!(" Root -> Child 1 -> Grandchild");
199 println!(" Root -> Child 2");
200 println!(" Created data container");
201
202 // Trigger garbage collection
203 println!("\n2. Trigger garbage collection...");
204 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
205 println!(" 回收了 {} 字节内存", freed);
206
207 // Verify data structure integrity
208 println!("\n3. Verify data structure integrity...");
209 {
210 println!(" Container root node: {}", container.root.name);
211 println!(" Metadata length: {}", container.metadata.len());
212 println!(
213 " Optional data exists: {}",
214 container.optional_data.is_some()
215 );
216 }
217
218 Ok(())
219}
220
221/// Demonstrate reference recovery functionality
222fn demonstrate_reference_recovery(
223 heap: &mut GcHeap,
224 partition: gc_lite::GcPartitionId,
225) -> GcResult<()> {
226 println!("1. Create object and get reference...");
227
228 let original_ref = unsafe {
229 heap.alloc_raw(
230 partition,
231 TestData {
232 value: 42,
233 name: "test".to_string(),
234 },
235 )
236 }
237 .map_err(|(err, _)| err)?;
238
239 let data_ref = original_ref.deref();
240 println!(" Original reference: {:?}", original_ref);
241 println!(" Data: {:?}", data_ref);
242
243 // Recover GcRef from reference
244 println!("\n2. Recover GcRef from reference...");
245 let recovered_ref = GcRef::try_from_ref(heap, data_ref);
246
247 match recovered_ref {
248 Some(recovered) => {
249 println!(" Recovery successful: {:?}", recovered);
250 let recovered_data = recovered.deref();
251 println!(" Recovered data: {:?}", recovered_data);
252 println!(" Data equal: {}", data_ref == recovered_data);
253 println!(" Reference equal: {}", original_ref == recovered);
254 }
255 None => println!(" Recovery failed (possibly type registration issue)"),
256 }
257
258 // Test invalid reference recovery - create an object not in GC heap
259 println!("\n3. Test invalid reference recovery...");
260 let local_data = TestData {
261 value: 100,
262 name: "local".to_string(),
263 };
264 let invalid_result = GcRef::try_from_ref(heap, &local_data);
265 println!(
266 " Invalid reference recovery result: {:?} (should be None)",
267 invalid_result
268 );
269
270 Ok(())
271}
272
273/// Demonstrate cross-context detection
274fn demonstrate_cross_context_detection() -> GcResult<()> {
275 println!("1. Create two independent heaps...");
276
277 let mut heap1 = new_heap();
278 let mut heap2 = new_heap();
279
280 let partition1 = heap1.create_partition();
281 let partition2 = heap2.create_partition();
282
283 let obj1 = unsafe {
284 heap1.alloc_root_raw(
285 partition1,
286 TestData {
287 value: 1,
288 name: "obj1".to_string(),
289 },
290 )
291 }
292 .map_err(|(e, _)| e)?;
293 let obj2 = unsafe {
294 heap2.alloc_raw(
295 partition2,
296 TestData {
297 value: 2,
298 name: "obj2".to_string(),
299 },
300 )
301 }
302 .map_err(|(e, _)| e)?;
303
304 println!("2. Test object source detection...");
305 assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
306 assert!(
307 !heap1.contains(obj2.node_ptr()),
308 "obj2 should not be from heap1"
309 );
310 assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
311 assert!(
312 !heap2.contains(obj1.node_ptr()),
313 "obj1 should not be from heap2"
314 );
315
316 println!(" ✓ Cross-context detection correct");
317
318 // Clean up
319 heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
320 heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
321
322 Ok(())
323}Source§impl GcHeap
impl GcHeap
Sourcepub fn create_partition(&mut self) -> GcPartitionId
pub fn create_partition(&mut self) -> GcPartitionId
Create a new partition.
Examples found in repository?
51fn main() -> GcResult<()> {
52 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
53 let scope = heap.create_partition();
54
55 let static_ref = alloc_static(&mut heap, scope, 10)?;
56 let other_ref = alloc_other(&mut heap, scope, 20)?;
57
58 println!("Static node value: {}", static_ref._value);
59 println!("Other node value: {}", other_ref._value);
60
61 println!("gc_node_usage example verified");
62
63 Ok(())
64}More examples
47fn main() -> GcResult<()> {
48 println!("=== Advanced features example of partitioned garbage collection system ===");
49
50 let mut heap = new_heap();
51 let partition = heap.create_partition();
52
53 // Demonstrate weak reference functionality
54 println!("\n=== Weak reference functionality demonstration ===");
55 demonstrate_weak_references(&mut heap, partition)?;
56
57 // Demonstrate circular reference handling
58 println!("\n=== Circular reference handling demonstration ===");
59 demonstrate_cyclic_references(&mut heap, partition)?;
60
61 // Demonstrate complex data structures
62 println!("\n=== Complex data structures demonstration ===");
63 demonstrate_complex_structures(&mut heap, partition)?;
64
65 // Demonstrate reference recovery functionality
66 println!("\n=== Reference recovery functionality demonstration ===");
67 demonstrate_reference_recovery(&mut heap, partition)?;
68
69 // Demonstrate cross-context detection
70 println!("\n=== Cross-context detection demonstration ===");
71 demonstrate_cross_context_detection()?;
72
73 println!("\nAll advanced feature demonstrations completed!");
74 Ok(())
75}
76
77/// Demonstrate weak reference functionality
78fn demonstrate_weak_references(
79 heap: &mut GcHeap,
80 partition: gc_lite::GcPartitionId,
81) -> GcResult<()> {
82 println!("1. Create strong and weak references...");
83
84 let strong_ref =
85 unsafe { heap.alloc_root_raw(partition, MyString(String::from("Strong Reference Data"))) }
86 .map_err(|(err, _)| err)?;
87
88 let weak_ref = heap.downgrade(&strong_ref);
89 println!(" Created strong reference: {:?}", strong_ref);
90 println!(" Created weak reference: {:?}", weak_ref);
91
92 // Upgrade weak reference
93 println!("\n2. Upgrade weak reference...");
94 match weak_ref.upgrade(heap) {
95 Some(upgraded) => {
96 let data = upgraded.deref();
97 println!(" Weak reference upgrade successful: '{}'", data);
98 assert_eq!(data, "Strong Reference Data");
99 }
100 None => println!(" Weak reference upgrade failed"),
101 }
102
103 // Try upgrading after releasing strong reference
104 println!("\n3. Upgrade weak reference after releasing strong reference...");
105 heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
106
107 match weak_ref.upgrade(heap) {
108 Some(_) => {
109 println!(" Weak reference can still be upgraded (object may still be in memory)")
110 }
111 None => println!(" Weak reference upgrade failed (object has been collected)"),
112 }
113
114 Ok(())
115}
116
117/// Demonstrate circular reference handling
118fn demonstrate_cyclic_references(
119 heap: &mut GcHeap,
120 partition: gc_lite::GcPartitionId,
121) -> GcResult<()> {
122 println!("1. Create circular reference nodes...");
123
124 // Create two mutually referencing nodes
125 let mut node1 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node A")) }
126 .map_err(|(err, _)| err)?;
127 let mut node2 = unsafe { heap.alloc_root_raw(partition, CyclicNode::new("Node B")) }
128 .map_err(|(err, _)| err)?;
129
130 // Establish circular references
131 {
132 node1.with_mut(heap, |n| n.set_partner(node2));
133 node2.with_mut(heap, |n| n.set_partner(node1));
134 }
135
136 println!(" Created node1: {}", node1.deref());
137 println!(" Created node2: {}", node2.deref());
138
139 // Trigger garbage collection
140 println!("\n2. Trigger garbage collection (circular references still exist)...");
141 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
142 println!(" 回收了 {} 字节内存", freed);
143
144 // Verify circular references still exist
145 println!("\n3. Verify circular references...");
146 println!(" Node1's partner: {}", node1.get_partner_name());
147 println!(" Node2's partner: {}", node2.get_partner_name());
148
149 // Clear root object status, let circular references be collected
150 println!("\n4. Clear root object status and trigger GC again...");
151 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
152 println!(
153 " Freed {} bytes of memory (circular references correctly collected)",
154 freed
155 );
156
157 Ok(())
158}
159
160/// Demonstrate complex data structures
161fn demonstrate_complex_structures(
162 heap: &mut GcHeap,
163 partition: gc_lite::GcPartitionId,
164) -> GcResult<()> {
165 println!("1. Create complex data structures...");
166
167 // Create multiple nodes
168 let mut root_node =
169 unsafe { heap.alloc_root_raw(partition, TreeNode::new("Root")) }.map_err(|(err, _)| err)?;
170 let mut child1 =
171 unsafe { heap.alloc_raw(partition, TreeNode::new("Child 1")) }.map_err(|(err, _)| err)?;
172 let child2 =
173 unsafe { heap.alloc_raw(partition, TreeNode::new("Child 2")) }.map_err(|(err, _)| err)?;
174 let grandchild = unsafe { heap.alloc_raw(partition, TreeNode::new("Grandchild")) }
175 .map_err(|(err, _)| err)?;
176
177 // Build tree structure
178 {
179 root_node.with_mut(heap, |n| n.add_child(child1));
180 root_node.with_mut(heap, |n| n.add_child(child2));
181 child1.with_mut(heap, |n| n.add_child(grandchild));
182 }
183
184 // Create data container
185 let container = unsafe {
186 heap.alloc_root_raw(
187 partition,
188 DataContainer {
189 root: root_node,
190 metadata: vec![1, 2, 3],
191 optional_data: Some(child1),
192 },
193 )
194 }
195 .map_err(|(err, _)| err)?;
196
197 println!(" Created tree structure:");
198 println!(" Root -> Child 1 -> Grandchild");
199 println!(" Root -> Child 2");
200 println!(" Created data container");
201
202 // Trigger garbage collection
203 println!("\n2. Trigger garbage collection...");
204 let freed = heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
205 println!(" 回收了 {} 字节内存", freed);
206
207 // Verify data structure integrity
208 println!("\n3. Verify data structure integrity...");
209 {
210 println!(" Container root node: {}", container.root.name);
211 println!(" Metadata length: {}", container.metadata.len());
212 println!(
213 " Optional data exists: {}",
214 container.optional_data.is_some()
215 );
216 }
217
218 Ok(())
219}
220
221/// Demonstrate reference recovery functionality
222fn demonstrate_reference_recovery(
223 heap: &mut GcHeap,
224 partition: gc_lite::GcPartitionId,
225) -> GcResult<()> {
226 println!("1. Create object and get reference...");
227
228 let original_ref = unsafe {
229 heap.alloc_raw(
230 partition,
231 TestData {
232 value: 42,
233 name: "test".to_string(),
234 },
235 )
236 }
237 .map_err(|(err, _)| err)?;
238
239 let data_ref = original_ref.deref();
240 println!(" Original reference: {:?}", original_ref);
241 println!(" Data: {:?}", data_ref);
242
243 // Recover GcRef from reference
244 println!("\n2. Recover GcRef from reference...");
245 let recovered_ref = GcRef::try_from_ref(heap, data_ref);
246
247 match recovered_ref {
248 Some(recovered) => {
249 println!(" Recovery successful: {:?}", recovered);
250 let recovered_data = recovered.deref();
251 println!(" Recovered data: {:?}", recovered_data);
252 println!(" Data equal: {}", data_ref == recovered_data);
253 println!(" Reference equal: {}", original_ref == recovered);
254 }
255 None => println!(" Recovery failed (possibly type registration issue)"),
256 }
257
258 // Test invalid reference recovery - create an object not in GC heap
259 println!("\n3. Test invalid reference recovery...");
260 let local_data = TestData {
261 value: 100,
262 name: "local".to_string(),
263 };
264 let invalid_result = GcRef::try_from_ref(heap, &local_data);
265 println!(
266 " Invalid reference recovery result: {:?} (should be None)",
267 invalid_result
268 );
269
270 Ok(())
271}
272
273/// Demonstrate cross-context detection
274fn demonstrate_cross_context_detection() -> GcResult<()> {
275 println!("1. Create two independent heaps...");
276
277 let mut heap1 = new_heap();
278 let mut heap2 = new_heap();
279
280 let partition1 = heap1.create_partition();
281 let partition2 = heap2.create_partition();
282
283 let obj1 = unsafe {
284 heap1.alloc_root_raw(
285 partition1,
286 TestData {
287 value: 1,
288 name: "obj1".to_string(),
289 },
290 )
291 }
292 .map_err(|(e, _)| e)?;
293 let obj2 = unsafe {
294 heap2.alloc_raw(
295 partition2,
296 TestData {
297 value: 2,
298 name: "obj2".to_string(),
299 },
300 )
301 }
302 .map_err(|(e, _)| e)?;
303
304 println!("2. Test object source detection...");
305 assert!(heap1.contains(obj1.node_ptr()), "obj1 should be from heap1");
306 assert!(
307 !heap1.contains(obj2.node_ptr()),
308 "obj2 should not be from heap1"
309 );
310 assert!(heap2.contains(obj2.node_ptr()), "obj2 should be from heap2");
311 assert!(
312 !heap2.contains(obj1.node_ptr()),
313 "obj1 should not be from heap2"
314 );
315
316 println!(" ✓ Cross-context detection correct");
317
318 // Clean up
319 heap1.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
320 heap2.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
321
322 Ok(())
323}38fn benchmark_object_sizes() {
39 let sizes = [10, 100, 500, 1000, 5000];
40
41 for &size in &sizes {
42 println!("\nTest object count: {}", size);
43
44 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
45 let partition = context.create_partition();
46
47 // Measure allocation performance
48 let alloc_start = Instant::now();
49 let mut objects = Vec::new();
50 for _i in 0..size {
51 let node = unsafe {
52 context.alloc_raw(
53 partition,
54 SimpleNode {
55 _data: vec![0u8; 100],
56 },
57 )
58 } // Each node 100 bytes
59 .unwrap();
60 objects.push(node);
61 }
62 let alloc_duration = alloc_start.elapsed();
63
64 println!(" Allocated {} objects in: {:?}", size, alloc_duration);
65 println!(
66 " Average allocation time per object: {:?}",
67 alloc_duration / size as u32
68 );
69
70 // Measure GC performance (all objects can be collected)
71 let gc_start = Instant::now();
72 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
73 let gc_duration = gc_start.elapsed();
74
75 println!(" GC回收 {} 字节耗时: {:?}", freed, gc_duration);
76 println!(
77 " Average collection time per byte: {:?}",
78 if freed > 0 {
79 gc_duration / freed as u32
80 } else {
81 Duration::from_nanos(0)
82 }
83 );
84 }
85}
86
87/// Test GC performance of complex object graphs
88fn benchmark_complex_graphs() {
89 let sizes = [100, 500, 1000];
90
91 for &size in &sizes {
92 println!("\nTest complex object graph size: {} nodes", size);
93
94 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
95 let partition = context.create_partition();
96
97 // Create complex object graph
98 let graph_start = Instant::now();
99 let mut nodes = Vec::new();
100
101 // Create all nodes
102 for _i in 0..size {
103 let node = unsafe {
104 context.alloc_raw(
105 partition,
106 GraphNode {
107 neighbors: Vec::new(),
108 },
109 )
110 }
111 .unwrap();
112 nodes.push(node);
113 }
114
115 // Establish complex dependencies
116 for i in 0..size {
117 {
118 // Each node points to subsequent nodes
119 for j in 1..=5 {
120 if i + j < size {
121 let n = nodes[i + j];
122 nodes[i].with_mut(&mut context, |node| node.neighbors.push(n));
123 }
124 }
125 // Every 10 nodes form a cycle
126 if i % 10 == 0 && i + 9 < size {
127 let n = nodes[i];
128 nodes[i + 9].with_mut(&mut context, |node| node.neighbors.push(n));
129 }
130 }
131 }
132 let graph_duration = graph_start.elapsed();
133
134 println!(" Built complex object graph in: {:?}", graph_duration);
135
136 // Measure GC performance
137 let gc_start = Instant::now();
138 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
139 let gc_duration = gc_start.elapsed();
140
141 println!(" GC回收 {} 字节耗时: {:?}", freed, gc_duration);
142 println!(
143 " Object graph complexity: average {} neighbors per node",
144 if size > 0 { (size * 5) / size } else { 0 }
145 );
146 }
147}
148
149/// Test memory usage efficiency
150fn benchmark_memory_efficiency() {
151 println!("\nTesting memory usage efficiency...");
152
153 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154 context.set_memory_limit(1024 * 1024); // 1MB global limit
155 let partition = context.create_partition();
156
157 // Allocate many small objects
158 let small_objects_count = 1000;
159 let mut small_objects = Vec::new();
160
161 for _i in 0..small_objects_count {
162 let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163 small_objects.push(obj);
164 }
165
166 if let Some(partition_info) = context.partition(partition) {
167 let used = partition_info.memory_used();
168 let limit = context.memory_limit();
169 let efficiency = if limit > 0 {
170 (used as f64 / limit as f64) * 100.0
171 } else {
172 0.0
173 };
174
175 println!(" After allocating {} small objects:", small_objects_count);
176 println!(
177 " Memory usage: {}/{} bytes ({:.1}%)",
178 used, limit, efficiency
179 );
180 println!(
181 " Average overhead per object: {} bytes",
182 if small_objects_count > 0 {
183 used / small_objects_count
184 } else {
185 0
186 }
187 );
188 }
189
190 // Collect all objects
191 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192 println!(" Collected all objects, freed {} bytes", freed);
193
194 // Verify complete memory collection
195 if let Some(partition_info) = context.partition(partition) {
196 let used_after = partition_info.memory_used();
197 println!(" Memory usage after collection: {} bytes", used_after);
198 println!(
199 " Memory collection rate: {:.1}%",
200 if freed > 0 {
201 (freed as f64 / (freed + used_after) as f64) * 100.0
202 } else {
203 0.0
204 }
205 );
206 }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211 println!("\nTesting automatic GC threshold performance...");
212
213 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214 context.set_memory_limit(2048); // 2KB global limit
215 let partition = context.create_partition();
216
217 // Set automatic GC threshold to 1.5KB
218 context.set_gc_threshold(1500);
219
220 // Allocate objects until automatic GC is triggered
221 let mut allocated_bytes = 0;
222 let mut object_count = 0;
223
224 println!(" Allocating objects until automatic GC is triggered...");
225
226 for _i in 0..100 {
227 // Try at most 100 times
228 // Allocate objects of about 100 bytes
229 let node = SimpleNode {
230 _data: vec![0u8; 100],
231 };
232 match unsafe { context.alloc_raw(partition, node) } {
233 Ok(_gc_ref) => {
234 allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235 object_count += 1;
236
237 // Check if approaching threshold
238 if let Some(partition_info) = context.partition(partition)
239 && partition_info.memory_used() >= 1500
240 {
241 println!(
242 " Reached automatic GC threshold, allocated {} objects",
243 object_count
244 );
245 println!(" Estimated allocated memory: {} bytes", allocated_bytes);
246 println!(
247 " Actual memory usage: {} bytes",
248 partition_info.memory_used()
249 );
250 break;
251 }
252 }
253 Err(_) => {
254 println!(" Allocation failed, automatic GC may have been triggered");
255 break;
256 }
257 }
258 }
259
260 // Manually trigger GC to see effect
261 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262 println!(" Manual GC freed {} bytes", freed);
263}34fn demonstrate_out_of_memory() -> GcResult<()> {
35 println!("1. Create limited memory partition...");
36
37 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
38 context.set_memory_limit(2048); // 2KB global limit
39 let partition_id = context.create_partition();
40
41 // Allocate first large object (1KB + header)
42 println!("2. Allocate first large object...");
43 let gc1: GcRef<LargeData> =
44 match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
45 Ok(gc_ref) => {
46 println!(" ✓ Successfully allocated first object (1KB)");
47 gc_ref
48 }
49 Err((error, _)) => {
50 println!(" ✗ First object allocation failed: {:?}", error);
51 return Ok(());
52 }
53 };
54
55 // Allocate second large object (1KB + header) - should exceed 2KB limit
56 println!("3. Try to allocate second large object...");
57 match unsafe { context.alloc_raw(partition_id, LargeData { data: [0; 1024] }) } {
58 Err((GcError::PartitionFull, _)) => {
59 println!(" ✓ Correctly detected partition full error");
60 }
61 Ok(_) => {
62 println!(" ✗ Expected partition full error, but allocation succeeded");
63 return Ok(());
64 }
65 Err((other_error, _)) => {
66 println!(
67 " ✗ Expected partition full error, but got: {:?}",
68 other_error
69 );
70 return Ok(());
71 }
72 }
73
74 // Clean up - through garbage collection instead of manual release
75 println!(" ✓ Automatic cleanup through GC");
76 context.garbage_collect(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
77
78 Ok(())
79}
80
81/// Demonstrate partition management errors
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83 println!("1. Test non-existent partition operations...");
84
85 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86 let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88 // Test allocating objects in non-existent partition
89 match unsafe {
90 context.alloc_raw(
91 invalid_partition,
92 TestData {
93 value: 42,
94 name: "test".to_string(),
95 },
96 )
97 } {
98 Err((GcError::PartitionNotFound, _)) => {
99 println!(" ✓ Allocating objects in non-existent partition returns correct error");
100 }
101 Ok(_) => {
102 println!(" ✗ Expected partition not found error, but allocation succeeded");
103 }
104 Err((other_error, _)) => {
105 println!(
106 " ✗ Expected partition not found error, but got: {:?}",
107 other_error
108 );
109 }
110 }
111
112 // Test getting non-existent partition information
113 let partition_info = context.partition(invalid_partition);
114 assert!(
115 partition_info.is_none(),
116 "Non-existent partition should return None"
117 );
118 println!(" ✓ Getting non-existent partition info returns None");
119
120 // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121 context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122 println!(" ✓ Removing non-existent partition silently fails");
123
124 println!("\n2. Test non-empty partition deletion...");
125 let partition_id = context.create_partition();
126
127 // Allocate objects in partition
128 let obj = unsafe {
129 context.alloc_raw(
130 partition_id,
131 TestData {
132 value: 1,
133 name: "obj".to_string(),
134 },
135 )
136 }
137 .unwrap();
138 let _ = obj;
139
140 // Try to delete non-empty partition (remove_partition will force cleanup)
141 context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142 println!(" ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144 Ok(())
145}
146
147/// Demonstrate GC threshold API errors
148fn demonstrate_gc_threshold_errors() -> GcResult<()> {
149 println!("1. Test GC threshold API...");
150
151 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
152 context.set_memory_limit(1024);
153 let _partition_id = context.create_partition();
154
155 // Test default values
156 println!("2. Test default threshold...");
157 assert_eq!(context.gc_threshold(), 0);
158 println!(" ✓ Default threshold is 0, automatic GC disabled");
159
160 // Test setting threshold
161 println!("3. Test setting threshold...");
162 context.set_gc_threshold(512);
163 assert_eq!(context.gc_threshold(), 512);
164 println!(" ✓ Successfully set threshold to 512, automatic GC enabled");
165
166 // Test setting threshold exceeding memory limit
167 println!("4. Test setting threshold exceeding memory limit...");
168 context.set_gc_threshold(2048);
169 // Since threshold exceeds memory limit, will be capped at 0.8x of limit (1024 * 8 / 10 = 819)
170 assert_eq!(context.gc_threshold(), 819);
171 println!(
172 " ✓ Setting threshold exceeding memory limit automatically adjusted to 0.8x of memory limit"
173 );
174
175 // Test disabling automatic GC
176 println!("5. Test disabling automatic GC...");
177 context.set_gc_threshold(0);
178 assert_eq!(context.gc_threshold(), 0);
179 println!(" ✓ Successfully disabled automatic GC, threshold set to 0");
180
181 Ok(())
182}49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 // Create garbage collection context
53 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 // Create two partitions
59 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 // Allocate objects in partition1
67 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 // Allocate objects in partition2
79 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 // Display partition status
88 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116 // No explicit `set_root` calls are needed for them.
117 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 // Manually trigger garbage collection for partition1
121 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 // Verify root objects are still valid
126 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 // Manually trigger garbage collection for partition2
131 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 // Verify partition2 root objects are still valid
136 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 // Trigger garbage collection for partition1 again to collect unreferenced objects
140 println!("\nTrigger garbage collection for partition1 again...");
141 // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142 // to test collection. For this example, we'll just collect other garbage.
143 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 // Verify remaining root objects are still valid
147 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 // Demonstrate automatic garbage collection
152 println!("\nDemonstrate automatic garbage collection...");
153
154 // Create a small partition to demonstrate automatic GC
155 let small_partition = heap.create_partition();
156
157 // Allocate multiple objects to fill partition
158 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 // Demonstrate weak references
166 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 // Upgrade weak reference
171 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 // Demonstrate complex types with GC references
184 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 // Establish references between nodes
191 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 // Trigger garbage collection, verify circular references are handled correctly
200 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 // Demonstrate partition deletion
205 println!("\nDemonstrate partition deletion:");
206
207 // Create an empty partition
208 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 // Delete empty partition
212 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 // Delete non-empty partition
216 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}Sourcepub fn remove_partition(
&mut self,
partition_id: GcPartitionId,
on_dispose: impl Fn(&GcHeap, &GcHead),
) -> usize
pub fn remove_partition( &mut self, partition_id: GcPartitionId, on_dispose: impl Fn(&GcHeap, &GcHead), ) -> usize
Remove a partition, and dispose unused nodes. For non-root partition, migrate xref nodes is optionally performed.
Examples found in repository?
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83 println!("1. Test non-existent partition operations...");
84
85 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86 let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88 // Test allocating objects in non-existent partition
89 match unsafe {
90 context.alloc_raw(
91 invalid_partition,
92 TestData {
93 value: 42,
94 name: "test".to_string(),
95 },
96 )
97 } {
98 Err((GcError::PartitionNotFound, _)) => {
99 println!(" ✓ Allocating objects in non-existent partition returns correct error");
100 }
101 Ok(_) => {
102 println!(" ✗ Expected partition not found error, but allocation succeeded");
103 }
104 Err((other_error, _)) => {
105 println!(
106 " ✗ Expected partition not found error, but got: {:?}",
107 other_error
108 );
109 }
110 }
111
112 // Test getting non-existent partition information
113 let partition_info = context.partition(invalid_partition);
114 assert!(
115 partition_info.is_none(),
116 "Non-existent partition should return None"
117 );
118 println!(" ✓ Getting non-existent partition info returns None");
119
120 // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121 context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122 println!(" ✓ Removing non-existent partition silently fails");
123
124 println!("\n2. Test non-empty partition deletion...");
125 let partition_id = context.create_partition();
126
127 // Allocate objects in partition
128 let obj = unsafe {
129 context.alloc_raw(
130 partition_id,
131 TestData {
132 value: 1,
133 name: "obj".to_string(),
134 },
135 )
136 }
137 .unwrap();
138 let _ = obj;
139
140 // Try to delete non-empty partition (remove_partition will force cleanup)
141 context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142 println!(" ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144 Ok(())
145}More examples
49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 // Create garbage collection context
53 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 // Create two partitions
59 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 // Allocate objects in partition1
67 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 // Allocate objects in partition2
79 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 // Display partition status
88 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116 // No explicit `set_root` calls are needed for them.
117 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 // Manually trigger garbage collection for partition1
121 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 // Verify root objects are still valid
126 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 // Manually trigger garbage collection for partition2
131 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 // Verify partition2 root objects are still valid
136 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 // Trigger garbage collection for partition1 again to collect unreferenced objects
140 println!("\nTrigger garbage collection for partition1 again...");
141 // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142 // to test collection. For this example, we'll just collect other garbage.
143 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 // Verify remaining root objects are still valid
147 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 // Demonstrate automatic garbage collection
152 println!("\nDemonstrate automatic garbage collection...");
153
154 // Create a small partition to demonstrate automatic GC
155 let small_partition = heap.create_partition();
156
157 // Allocate multiple objects to fill partition
158 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 // Demonstrate weak references
166 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 // Upgrade weak reference
171 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 // Demonstrate complex types with GC references
184 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 // Establish references between nodes
191 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 // Trigger garbage collection, verify circular references are handled correctly
200 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 // Demonstrate partition deletion
205 println!("\nDemonstrate partition deletion:");
206
207 // Create an empty partition
208 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 // Delete empty partition
212 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 // Delete non-empty partition
216 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}Sourcepub fn partition(&self, partition_id: GcPartitionId) -> Option<&GcPartition>
pub fn partition(&self, partition_id: GcPartitionId) -> Option<&GcPartition>
Get partition information
Examples found in repository?
150fn benchmark_memory_efficiency() {
151 println!("\nTesting memory usage efficiency...");
152
153 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
154 context.set_memory_limit(1024 * 1024); // 1MB global limit
155 let partition = context.create_partition();
156
157 // Allocate many small objects
158 let small_objects_count = 1000;
159 let mut small_objects = Vec::new();
160
161 for _i in 0..small_objects_count {
162 let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
163 small_objects.push(obj);
164 }
165
166 if let Some(partition_info) = context.partition(partition) {
167 let used = partition_info.memory_used();
168 let limit = context.memory_limit();
169 let efficiency = if limit > 0 {
170 (used as f64 / limit as f64) * 100.0
171 } else {
172 0.0
173 };
174
175 println!(" After allocating {} small objects:", small_objects_count);
176 println!(
177 " Memory usage: {}/{} bytes ({:.1}%)",
178 used, limit, efficiency
179 );
180 println!(
181 " Average overhead per object: {} bytes",
182 if small_objects_count > 0 {
183 used / small_objects_count
184 } else {
185 0
186 }
187 );
188 }
189
190 // Collect all objects
191 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
192 println!(" Collected all objects, freed {} bytes", freed);
193
194 // Verify complete memory collection
195 if let Some(partition_info) = context.partition(partition) {
196 let used_after = partition_info.memory_used();
197 println!(" Memory usage after collection: {} bytes", used_after);
198 println!(
199 " Memory collection rate: {:.1}%",
200 if freed > 0 {
201 (freed as f64 / (freed + used_after) as f64) * 100.0
202 } else {
203 0.0
204 }
205 );
206 }
207}
208
209/// Test automatic GC threshold performance
210fn benchmark_auto_gc_threshold() {
211 println!("\nTesting automatic GC threshold performance...");
212
213 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
214 context.set_memory_limit(2048); // 2KB global limit
215 let partition = context.create_partition();
216
217 // Set automatic GC threshold to 1.5KB
218 context.set_gc_threshold(1500);
219
220 // Allocate objects until automatic GC is triggered
221 let mut allocated_bytes = 0;
222 let mut object_count = 0;
223
224 println!(" Allocating objects until automatic GC is triggered...");
225
226 for _i in 0..100 {
227 // Try at most 100 times
228 // Allocate objects of about 100 bytes
229 let node = SimpleNode {
230 _data: vec![0u8; 100],
231 };
232 match unsafe { context.alloc_raw(partition, node) } {
233 Ok(_gc_ref) => {
234 allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
235 object_count += 1;
236
237 // Check if approaching threshold
238 if let Some(partition_info) = context.partition(partition)
239 && partition_info.memory_used() >= 1500
240 {
241 println!(
242 " Reached automatic GC threshold, allocated {} objects",
243 object_count
244 );
245 println!(" Estimated allocated memory: {} bytes", allocated_bytes);
246 println!(
247 " Actual memory usage: {} bytes",
248 partition_info.memory_used()
249 );
250 break;
251 }
252 }
253 Err(_) => {
254 println!(" Allocation failed, automatic GC may have been triggered");
255 break;
256 }
257 }
258 }
259
260 // Manually trigger GC to see effect
261 let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
262 println!(" Manual GC freed {} bytes", freed);
263}More examples
82fn demonstrate_partition_management_errors() -> GcResult<()> {
83 println!("1. Test non-existent partition operations...");
84
85 let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
86 let invalid_partition = gc_lite::GcPartitionId(9999); // Non-existent partition
87
88 // Test allocating objects in non-existent partition
89 match unsafe {
90 context.alloc_raw(
91 invalid_partition,
92 TestData {
93 value: 42,
94 name: "test".to_string(),
95 },
96 )
97 } {
98 Err((GcError::PartitionNotFound, _)) => {
99 println!(" ✓ Allocating objects in non-existent partition returns correct error");
100 }
101 Ok(_) => {
102 println!(" ✗ Expected partition not found error, but allocation succeeded");
103 }
104 Err((other_error, _)) => {
105 println!(
106 " ✗ Expected partition not found error, but got: {:?}",
107 other_error
108 );
109 }
110 }
111
112 // Test getting non-existent partition information
113 let partition_info = context.partition(invalid_partition);
114 assert!(
115 partition_info.is_none(),
116 "Non-existent partition should return None"
117 );
118 println!(" ✓ Getting non-existent partition info returns None");
119
120 // Test removing non-existent partition (remove_partition doesn't return error, just silently fails)
121 context.remove_partition(invalid_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
122 println!(" ✓ Removing non-existent partition silently fails");
123
124 println!("\n2. Test non-empty partition deletion...");
125 let partition_id = context.create_partition();
126
127 // Allocate objects in partition
128 let obj = unsafe {
129 context.alloc_raw(
130 partition_id,
131 TestData {
132 value: 1,
133 name: "obj".to_string(),
134 },
135 )
136 }
137 .unwrap();
138 let _ = obj;
139
140 // Try to delete non-empty partition (remove_partition will force cleanup)
141 context.remove_partition(partition_id, GcHeap::DUMMY_DISPOSE_CALLBACK);
142 println!(" ✓ Successfully deleted non-empty partition (root objects were force cleaned)");
143
144 Ok(())
145}49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 // Create garbage collection context
53 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 // Create two partitions
59 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 // Allocate objects in partition1
67 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 // Allocate objects in partition2
79 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 // Display partition status
88 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116 // No explicit `set_root` calls are needed for them.
117 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 // Manually trigger garbage collection for partition1
121 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 // Verify root objects are still valid
126 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 // Manually trigger garbage collection for partition2
131 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 // Verify partition2 root objects are still valid
136 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 // Trigger garbage collection for partition1 again to collect unreferenced objects
140 println!("\nTrigger garbage collection for partition1 again...");
141 // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142 // to test collection. For this example, we'll just collect other garbage.
143 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 // Verify remaining root objects are still valid
147 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 // Demonstrate automatic garbage collection
152 println!("\nDemonstrate automatic garbage collection...");
153
154 // Create a small partition to demonstrate automatic GC
155 let small_partition = heap.create_partition();
156
157 // Allocate multiple objects to fill partition
158 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 // Demonstrate weak references
166 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 // Upgrade weak reference
171 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 // Demonstrate complex types with GC references
184 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 // Establish references between nodes
191 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 // Trigger garbage collection, verify circular references are handled correctly
200 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 // Demonstrate partition deletion
205 println!("\nDemonstrate partition deletion:");
206
207 // Create an empty partition
208 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 // Delete empty partition
212 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 // Delete non-empty partition
216 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}Sourcepub fn partition_mut(
&mut self,
partition_id: GcPartitionId,
) -> Option<&mut GcPartition>
pub fn partition_mut( &mut self, partition_id: GcPartitionId, ) -> Option<&mut GcPartition>
Get partition information
Sourcepub fn partition_ids(&self) -> Vec<GcPartitionId>
pub fn partition_ids(&self) -> Vec<GcPartitionId>
Get all partition IDs
Examples found in repository?
49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 // Create garbage collection context
53 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 // Create two partitions
59 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 // Allocate objects in partition1
67 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 // Allocate objects in partition2
79 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 // Display partition status
88 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116 // No explicit `set_root` calls are needed for them.
117 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 // Manually trigger garbage collection for partition1
121 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 // Verify root objects are still valid
126 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 // Manually trigger garbage collection for partition2
131 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 // Verify partition2 root objects are still valid
136 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 // Trigger garbage collection for partition1 again to collect unreferenced objects
140 println!("\nTrigger garbage collection for partition1 again...");
141 // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142 // to test collection. For this example, we'll just collect other garbage.
143 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 // Verify remaining root objects are still valid
147 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 // Demonstrate automatic garbage collection
152 println!("\nDemonstrate automatic garbage collection...");
153
154 // Create a small partition to demonstrate automatic GC
155 let small_partition = heap.create_partition();
156
157 // Allocate multiple objects to fill partition
158 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 // Demonstrate weak references
166 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 // Upgrade weak reference
171 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 // Demonstrate complex types with GC references
184 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 // Establish references between nodes
191 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 // Trigger garbage collection, verify circular references are handled correctly
200 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 // Demonstrate partition deletion
205 println!("\nDemonstrate partition deletion:");
206
207 // Create an empty partition
208 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 // Delete empty partition
212 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 // Delete non-empty partition
216 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}Source§impl GcHeap
impl GcHeap
pub fn scope_max_depth(&self) -> u8
Sourcepub fn scope(&self, depth: u8) -> Option<&GcScopeState<'_>>
pub fn scope(&self, depth: u8) -> Option<&GcScopeState<'_>>
get scope by depth (peek, without modifying stack)
pub fn current_scope(&self) -> Option<&GcScopeState<'_>>
pub fn with_current_scope<R>( &mut self, f: impl FnOnce(&mut GcScopeState<'_>) -> R, ) -> Option<R>
pub fn new_scope<'s>(&'s mut self, partition_id: GcPartitionId) -> GcScope<'s>
pub fn with_new_scope<R>( &mut self, partition_id: GcPartitionId, f: impl FnOnce(GcScope<'_>) -> R, ) -> R
Source§impl GcHeap
impl GcHeap
pub fn create_trace_ctx(&self, cap: usize) -> GcTraceCtx<'_>
Sourcepub fn trace_node(&self, node: NonNull<GcHead>, gcx: &mut GcTraceCtx<'_>)
pub fn trace_node(&self, node: NonNull<GcHead>, gcx: &mut GcTraceCtx<'_>)
Trace direct children of a node into the given trace context
pub fn traverse_start(&mut self, partition_id: GcPartitionId)
Sourcepub fn traverse(
&mut self,
node: NonNull<GcHead>,
filter: GcPartitionId,
callback: impl FnMut(NonNull<GcHead>, Option<NonNull<GcHead>>),
)
pub fn traverse( &mut self, node: NonNull<GcHead>, filter: GcPartitionId, callback: impl FnMut(NonNull<GcHead>, Option<NonNull<GcHead>>), )
Traverses the node tree starting at node in depth-first order,
invoking callback on each visited node with its optional parent.
If filter is non-null, only nodes in the specified partition are visited.
Source§impl GcHeap
impl GcHeap
Sourcepub fn downgrade<T: GcNode>(&mut self, gc_ref: &GcRef<T>) -> GcWeak<T>
pub fn downgrade<T: GcNode>(&mut self, gc_ref: &GcRef<T>) -> GcWeak<T>
Create weak reference.
Examples found in repository?
78fn demonstrate_weak_references(
79 heap: &mut GcHeap,
80 partition: gc_lite::GcPartitionId,
81) -> GcResult<()> {
82 println!("1. Create strong and weak references...");
83
84 let strong_ref =
85 unsafe { heap.alloc_root_raw(partition, MyString(String::from("Strong Reference Data"))) }
86 .map_err(|(err, _)| err)?;
87
88 let weak_ref = heap.downgrade(&strong_ref);
89 println!(" Created strong reference: {:?}", strong_ref);
90 println!(" Created weak reference: {:?}", weak_ref);
91
92 // Upgrade weak reference
93 println!("\n2. Upgrade weak reference...");
94 match weak_ref.upgrade(heap) {
95 Some(upgraded) => {
96 let data = upgraded.deref();
97 println!(" Weak reference upgrade successful: '{}'", data);
98 assert_eq!(data, "Strong Reference Data");
99 }
100 None => println!(" Weak reference upgrade failed"),
101 }
102
103 // Try upgrading after releasing strong reference
104 println!("\n3. Upgrade weak reference after releasing strong reference...");
105 heap.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
106
107 match weak_ref.upgrade(heap) {
108 Some(_) => {
109 println!(" Weak reference can still be upgraded (object may still be in memory)")
110 }
111 None => println!(" Weak reference upgrade failed (object has been collected)"),
112 }
113
114 Ok(())
115}More examples
49fn main() -> GcResult<()> {
50 println!("=== Basic usage example of partitioned garbage collection system ===");
51
52 // Create garbage collection context
53 let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
54
55 println!("Initial state:");
56 println!(" Number of partitions: {}", heap.partition_ids().len());
57
58 // Create two partitions
59 println!("\nCreate partitions:");
60 let partition1 = heap.create_partition();
61 let partition2 = heap.create_partition();
62 println!(" Created partition1: {:?}", partition1);
63 println!(" Created partition2: {:?}", partition2);
64 println!(" Number of partitions: {}", heap.partition_ids().len());
65
66 // Allocate objects in partition1
67 println!("\nAllocate objects in partition1:");
68 let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
69 .map_err(|(err, _)| err)?;
70 let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
71 let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
72 .map_err(|(err, _)| err)?;
73
74 println!(" Created string: '{}'", obj1.deref());
75 println!(" Created number: {}", obj2.deref());
76 println!(" Created string: '{}'", obj3.deref());
77
78 // Allocate objects in partition2
79 println!("\nAllocate objects in partition2:");
80 let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
81 .map_err(|(err, _)| err)?;
82 let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
83
84 println!(" Created string: '{}'", obj4.deref());
85 println!(" Created number: {}", obj5.deref());
86
87 // Display partition status
88 println!("\nPartition status:");
89 for partition_id in heap.partition_ids() {
90 if let Some(partition) = heap.partition(partition_id) {
91 let limit = heap.memory_limit();
92 let usage = if limit > 0 {
93 format!(
94 "{}/{} bytes ({:.1}%)",
95 partition.memory_used(),
96 limit,
97 (partition.memory_used() as f64 / limit as f64) * 100.0
98 )
99 } else {
100 format!("{}/∞ bytes", partition.memory_used())
101 };
102 println!(
103 " {:?}: {} [自动GC: {}]",
104 partition_id,
105 usage,
106 if heap.gc_threshold() > 0 {
107 "Enabled"
108 } else {
109 "Disabled"
110 }
111 );
112 }
113 }
114
115 // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
116 // No explicit `set_root` calls are needed for them.
117 println!("\nRoot objects are held by variables:");
118 println!(" Roots: obj1, obj2, obj3, obj4, obj5");
119
120 // Manually trigger garbage collection for partition1
121 println!("\nManually trigger garbage collection for partition1...");
122 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
123 println!(" Collected {} bytes", freed);
124
125 // Verify root objects are still valid
126 println!("\nVerify partition1 root objects are still valid:");
127 println!(" Object1: '{}'", obj1.deref());
128 println!(" Object2: {}", obj2.deref());
129
130 // Manually trigger garbage collection for partition2
131 println!("\nManually trigger garbage collection for partition2...");
132 let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
133 println!(" Collected {} bytes", freed);
134
135 // Verify partition2 root objects are still valid
136 println!("\nVerify partition2 root objects are still valid:");
137 println!(" Object4: '{}'", obj4.deref());
138
139 // Trigger garbage collection for partition1 again to collect unreferenced objects
140 println!("\nTrigger garbage collection for partition1 again...");
141 // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
142 // to test collection. For this example, we'll just collect other garbage.
143 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
144 println!(" Collected {} bytes", freed);
145
146 // Verify remaining root objects are still valid
147 println!("\nVerify remaining root objects are still valid:");
148 println!(" Object1: '{}'", obj1.deref());
149 println!(" Object2: {} (still a root)", obj2.deref());
150
151 // Demonstrate automatic garbage collection
152 println!("\nDemonstrate automatic garbage collection...");
153
154 // Create a small partition to demonstrate automatic GC
155 let small_partition = heap.create_partition();
156
157 // Allocate multiple objects to fill partition
158 for i in 0..5 {
159 let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
160 .map_err(|(err, _)| err)?;
161 }
162
163 println!(" Allocated 5 objects in small partition");
164
165 // Demonstrate weak references
166 println!("\nDemonstrate weak references:");
167 let weak_ref = heap.downgrade(&obj1);
168 println!(" Created weak reference: {:?}", weak_ref);
169
170 // Upgrade weak reference
171 match weak_ref.upgrade(&heap) {
172 Some(strong_ref) => {
173 println!(
174 " Weak reference upgrade successful: '{}'",
175 strong_ref.deref()
176 );
177 }
178 None => {
179 println!(" Weak reference upgrade failed");
180 }
181 }
182
183 // Demonstrate complex types with GC references
184 println!("\nDemonstrate complex types with GC references:");
185 let mut node1 =
186 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
187 let mut node2 =
188 unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
189
190 // Establish references between nodes
191 {
192 node1.with_mut(&mut heap, |n| n.add_child(node2));
193 node2.with_mut(&mut heap, |n| n.add_child(node1));
194 }
195
196 println!(" Created node1: {}", node1.deref());
197 println!(" Created node2: {}", node2.deref());
198
199 // Trigger garbage collection, verify circular references are handled correctly
200 println!("\nGarbage collection for handling circular references...");
201 let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
202 println!(" 回收了 {} 字节内存", freed);
203
204 // Demonstrate partition deletion
205 println!("\nDemonstrate partition deletion:");
206
207 // Create an empty partition
208 let empty_partition = heap.create_partition();
209 println!(" Created empty partition: {:?}", empty_partition);
210
211 // Delete empty partition
212 heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
213 println!(" Deleted empty partition successfully");
214
215 // Delete non-empty partition
216 heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
217 println!(" Deleted non-empty partition successfully");
218
219 println!("\nExample completed!");
220 Ok(())
221}