RSGC

Semi-conservative Mark&Sweep Garbage Collector inspired by Shenandoah for Rust written in Rust.

Features

Benchmarks

To run benchmarks you need .NET and Java installed, enter benchmarks/binarytrees directory and run make.

Architecture

Allocation

Allocation happens in regions, if allocation request size is larger than humongous object threshold then multiple regions are used to allocate object, otherwise object gets allocated in free-list. Fast path also includes per-thread TLAB for speeding up allocation.

Collection Cycle

RSGC essentially has 3 GCs: Concurrent, Degenerated and Full GC. Concurrent GC gets periodically scheduled by background controller thread. If too much allocation happens while concurrent GC runs or OOM happens we switch to degenerated GC. Degenerated GC simply finished Concurrent GC work in stop-the-world phase. If too many degenerated cycles happen we start Full GC. Full GC does GC cycle fully in stop-the-world.

When GC starts?

It depends on heuristics choosen. At the moment only adaptive and compact are available.

Concurrency

RSGC is Concurrent Mark-And-Sweep. This means you need to ensure that objects are properly traced by collector when marking is running. For this Thread::write_barrier should be invoked right after write of field to an object: ```rust

fn foo(thread: &mut Thread, obj: Handle, field: Handle) { obj.asmut().field = field; thread.writebarrier(obj); // possibly push obj to mark worklist } ```

Safepoints

Safepoints are the only way GC can synchronize all threads at some point in time to perform some operations that can't be performed concurrently with threads running. For safepoint to happen you should invoke Thread::safepoint: ```rust

fn someexpensivefunc(thread: &mut Thread) { thread.safepoint(); // safepoint at entry

while /* some condition */ {
    // safepoint at loop header
    thread.safepoint();
    /* some expensive code */
}

} ```

Rooting

You do not need to somehow root your objects. GC is able to discover objects on stack automatically. You can use Heap::add_global_root to add walk-able root object in case not all your objects reside on stack.