Skip to main content

GcPartition

Struct GcPartition 

Source
pub struct GcPartition { /* private fields */ }

Implementations§

Source§

impl GcPartition

Source

pub fn nodes_mut(&mut self) -> NodeLinkIterMut<'_>

Source§

impl GcPartition

Source

pub fn new(capacity: usize, max_alloc: usize) -> Self

Create a new partition.

§Parameters
  • capacity: arena size in bytes. 0 = disable arena for this partition (all allocations go through system malloc directly).
  • max_alloc: allocations larger than this skip the arena. When capacity == 0 this is forced to 0.
Source

pub fn memory_used(&self) -> usize

Examples found in repository?
examples/performance_benchmark.rs (line 173)
156fn benchmark_memory_efficiency() {
157    println!("\nTesting memory usage efficiency...");
158
159    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
160    context.set_memory_limit(1024 * 1024); // 1MB global limit
161    let partition = context.create_partition(64 * 1024, 16 * 1024);
162
163    // Allocate many small objects
164    let small_objects_count = 1000;
165    let mut small_objects = Vec::new();
166
167    for _i in 0..small_objects_count {
168        let obj = unsafe { context.alloc_raw(partition, SmallData {}) }.unwrap();
169        small_objects.push(obj);
170    }
171
172    if let Some(partition_info) = context.partition(partition) {
173        let used = partition_info.memory_used();
174        let limit = context.memory_limit();
175        let efficiency = if limit > 0 {
176            (used as f64 / limit as f64) * 100.0
177        } else {
178            0.0
179        };
180
181        println!("  After allocating {} small objects:", small_objects_count);
182        println!(
183            "  Memory usage: {}/{} bytes ({:.1}%)",
184            used, limit, efficiency
185        );
186        println!(
187            "  Average overhead per object: {} bytes",
188            if small_objects_count > 0 {
189                used / small_objects_count
190            } else {
191                0
192            }
193        );
194    }
195
196    // Collect all objects
197    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
198    println!("  Collected all objects, freed {} bytes", freed);
199
200    // Verify complete memory collection
201    if let Some(partition_info) = context.partition(partition) {
202        let used_after = partition_info.memory_used();
203        println!("  Memory usage after collection: {} bytes", used_after);
204        println!(
205            "  Memory collection rate: {:.1}%",
206            if freed > 0 {
207                (freed as f64 / (freed + used_after) as f64) * 100.0
208            } else {
209                0.0
210            }
211        );
212    }
213}
214
215/// Test automatic GC threshold performance
216fn benchmark_auto_gc_threshold() {
217    println!("\nTesting automatic GC threshold performance...");
218
219    let mut context = GcHeap::new(&GC_TYPE_REGISTRY);
220    context.set_memory_limit(2048); // 2KB global limit
221    let partition = context.create_partition(64 * 1024, 16 * 1024);
222
223    // Set automatic GC threshold to 1.5KB
224    context.set_gc_threshold(1500);
225
226    // Allocate objects until automatic GC is triggered
227    let mut allocated_bytes = 0;
228    let mut object_count = 0;
229
230    println!("  Allocating objects until automatic GC is triggered...");
231
232    for _i in 0..100 {
233        // Try at most 100 times
234        // Allocate objects of about 100 bytes
235        let node = SimpleNode {
236            _data: vec![0u8; 100],
237        };
238        match unsafe { context.alloc_raw(partition, node) } {
239            Ok(_gc_ref) => {
240                allocated_bytes += 100 + std::mem::size_of::<GcRef<SimpleNode>>(); // Estimated size
241                object_count += 1;
242
243                // Check if approaching threshold
244                if let Some(partition_info) = context.partition(partition)
245                    && partition_info.memory_used() >= 1500
246                {
247                    println!(
248                        "  Reached automatic GC threshold, allocated {} objects",
249                        object_count
250                    );
251                    println!("  Estimated allocated memory: {} bytes", allocated_bytes);
252                    println!(
253                        "  Actual memory usage: {} bytes",
254                        partition_info.memory_used()
255                    );
256                    break;
257                }
258            }
259            Err(_) => {
260                println!("  Allocation failed, automatic GC may have been triggered");
261                break;
262            }
263        }
264    }
265
266    // Manually trigger GC to see effect
267    let freed = context.garbage_collect(partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
268    println!("  Manual GC freed {} bytes", freed);
269}
More examples
Hide additional examples
examples/basic_usage.rs (line 93)
47fn main() -> GcResult<()> {
48    println!("=== Basic usage example of partitioned garbage collection system ===");
49
50    // Create garbage collection context
51    let mut heap = GcHeap::new(&GC_TYPE_REGISTRY);
52
53    println!("Initial state:");
54    println!("  Number of partitions: {}", heap.partition_ids().len());
55
56    // Create two partitions
57    println!("\nCreate partitions:");
58    let partition1 = heap.create_partition(64 * 1024, 16 * 1024);
59    let partition2 = heap.create_partition(64 * 1024, 16 * 1024);
60    println!("  Created partition1: {:?}", partition1);
61    println!("  Created partition2: {:?}", partition2);
62    println!("  Number of partitions: {}", heap.partition_ids().len());
63
64    // Allocate objects in partition1
65    println!("\nAllocate objects in partition1:");
66    let obj1 = unsafe { heap.alloc_raw(partition1, MyString(String::from("Hello"))) }
67        .map_err(|(err, _)| err)?;
68    let obj2 = unsafe { heap.alloc_raw(partition1, MyI32(42)) }.map_err(|(err, _)| err)?;
69    let obj3 = unsafe { heap.alloc_raw(partition1, MyString(String::from("VectorData"))) }
70        .map_err(|(err, _)| err)?;
71
72    println!("  Created string: '{}'", unsafe { obj1.as_ref() });
73    println!("  Created number: {}", unsafe { obj2.as_ref() });
74    println!("  Created string: '{}'", unsafe { obj3.as_ref() });
75
76    // Allocate objects in partition2
77    println!("\nAllocate objects in partition2:");
78    let obj4 = unsafe { heap.alloc_raw(partition2, MyString(String::from("World"))) }
79        .map_err(|(err, _)| err)?;
80    let obj5 = unsafe { heap.alloc_raw(partition2, MyI32(99)) }.map_err(|(err, _)| err)?;
81
82    println!("  Created string: '{}'", unsafe { obj4.as_ref() });
83    println!("  Created number: {}", unsafe { obj5.as_ref() });
84
85    // Display partition status
86    println!("\nPartition status:");
87    for partition_id in heap.partition_ids() {
88        if let Some(partition) = heap.partition(partition_id) {
89            let limit = heap.memory_limit();
90            let usage = if limit > 0 {
91                format!(
92                    "{}/{} bytes ({:.1}%)",
93                    partition.memory_used(),
94                    limit,
95                    (partition.memory_used() as f64 / limit as f64) * 100.0
96                )
97            } else {
98                format!("{}/∞ bytes", partition.memory_used())
99            };
100            println!(
101                "  {:?}: {} [自动GC: {}]",
102                partition_id,
103                usage,
104                if heap.gc_threshold() > 0 {
105                    "Enabled"
106                } else {
107                    "Disabled"
108                }
109            );
110        }
111    }
112
113    // Root objects are now implicitly managed by stack variables (e.g., obj1, obj2).
114    // No explicit `set_root` calls are needed for them.
115    println!("\nRoot objects are held by variables:");
116    println!("  Roots: obj1, obj2, obj3, obj4, obj5");
117
118    // Manually trigger garbage collection for partition1
119    println!("\nManually trigger garbage collection for partition1...");
120    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
121    println!("  Collected {} bytes", freed);
122
123    // Verify root objects are still valid
124    println!("\nVerify partition1 root objects are still valid:");
125    println!("  Object1: '{}'", unsafe { obj1.as_ref() });
126    println!("  Object2: {}", unsafe { obj2.as_ref() });
127
128    // Manually trigger garbage collection for partition2
129    println!("\nManually trigger garbage collection for partition2...");
130    let freed = heap.garbage_collect(partition2, GcHeap::DUMMY_DISPOSE_CALLBACK);
131    println!("  Collected {} bytes", freed);
132
133    // Verify partition2 root objects are still valid
134    println!("\nVerify partition2 root objects are still valid:");
135    println!("  Object4: '{}'", unsafe { obj4.as_ref() });
136
137    // Trigger garbage collection for partition1 again to collect unreferenced objects
138    println!("\nTrigger garbage collection for partition1 again...");
139    // obj2 is no longer explicitly un-rooted, but we can simulate it going out of scope
140    // to test collection. For this example, we'll just collect other garbage.
141    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
142    println!("  Collected {} bytes", freed);
143
144    // Verify remaining root objects are still valid
145    println!("\nVerify remaining root objects are still valid:");
146    println!("  Object1: '{}'", unsafe { obj1.as_ref() });
147    println!("  Object2: {} (still a root)", unsafe { obj2.as_ref() });
148
149    // Demonstrate automatic garbage collection
150    println!("\nDemonstrate automatic garbage collection...");
151
152    // Create a small partition to demonstrate automatic GC
153    let small_partition = heap.create_partition(64 * 1024, 16 * 1024);
154
155    // Allocate multiple objects to fill partition
156    for i in 0..5 {
157        let _obj = unsafe { heap.alloc_raw(small_partition, MyString(format!("Object {}", i))) }
158            .map_err(|(err, _)| err)?;
159    }
160
161    println!("  Allocated 5 objects in small partition");
162
163    // Demonstrate weak references
164    println!("\nDemonstrate weak references:");
165    let weak_ref = heap.downgrade(&obj1);
166    println!("  Created weak reference: {:?}", weak_ref);
167
168    // Upgrade weak reference
169    match weak_ref.upgrade(&heap) {
170        Some(strong_ref) => {
171            println!("  Weak reference upgrade successful: '{}'", &*strong_ref);
172        }
173        None => {
174            println!("  Weak reference upgrade failed");
175        }
176    }
177
178    // Demonstrate complex types with GC references
179    println!("\nDemonstrate complex types with GC references:");
180    let mut node1 =
181        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 1")) }.map_err(|(err, _)| err)?;
182    let mut node2 =
183        unsafe { heap.alloc_raw(partition1, TestNode::new("Node 2")) }.map_err(|(err, _)| err)?;
184
185    // Establish references between nodes
186    {
187        unsafe {
188            node1.with_write_barrier(&mut heap, |n| n.add_child(node2));
189        }
190        unsafe {
191            node2.with_write_barrier(&mut heap, |n| n.add_child(node1));
192        }
193    }
194
195    println!("  Created node1: {}", unsafe { node1.as_ref() });
196    println!("  Created node2: {}", unsafe { node2.as_ref() });
197
198    // Trigger garbage collection, verify circular references are handled correctly
199    println!("\nGarbage collection for handling circular references...");
200    let freed = heap.garbage_collect(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
201    println!("  回收了 {} 字节内存", freed);
202
203    // Demonstrate partition deletion
204    println!("\nDemonstrate partition deletion:");
205
206    // Create an empty partition
207    let empty_partition = heap.create_partition(64 * 1024, 16 * 1024);
208    println!("  Created empty partition: {:?}", empty_partition);
209
210    // Delete empty partition
211    heap.remove_partition(empty_partition, GcHeap::DUMMY_DISPOSE_CALLBACK);
212    println!("  Deleted empty partition successfully");
213
214    // Delete non-empty partition
215    heap.remove_partition(partition1, GcHeap::DUMMY_DISPOSE_CALLBACK);
216    println!("  Deleted non-empty partition successfully");
217
218    println!("\nExample completed!");
219    Ok(())
220}
Source

pub const fn is_marking(&self) -> bool

Trait Implementations§

Source§

impl Debug for GcPartition

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.