2 releases

0.1.1 May 1, 2020
0.1.0 Apr 29, 2020

#600 in Memory management

34 downloads per month

MIT license

1.5K SLoC


cgc is generational copying garbage collector.

This branch implements signle-threaded version that does not have anything to deal with concurrency and synchronization.


cgc uses semispace garbage collection to keep GC simple and generations to improve GC latency.

Who this crate is for

  • For people developing programming language runtime, no matter is language dynamically or statically typed.
  • Game developers where lot's of assets is loaded and some of them not cleared automatically.
  • For someone who is doing big & complex graph structures and do not want to mess with reference counting.
  • For people that deal with huge heaps and fragmentation, cgc removes fragmentation using copying garbage collection.

Logging support

cgc supports logging. To alloc printing trace add feature trace-gc to features and to pring GC timings add trace-gc-timings feature.

Comparison to other GC crates


Advantages of broom:

  • Less dependencies (depends only on one crate hashbrown).
  • Very small & simple implementation.

Disadvantages of broom:

  • Mark'n Sweep algorithm. Mark&sweep may be really slow on huge heaps.
  • No memory defragmentation and generations. Without memory defragmentation it is really slow to allocate memory when heap is fragmented and without generations collections may be really slow since GC will collect entire heap.
  • No concurrent garbage collection support.


Advantages of gc:

  • No dependencies
  • Easy to make GC object,just use #[derive(Trace)].

Disadvantages of gc:

gc crate has the same disadvantages as broom crate, it uses mark'n sweep and does not have any memory defragmentation.


cgc is simple to use all you have to do is implement Traceable and Finalizer for your type and you now have GC object!

extern crate cgc_single_threaded as cgc;

use cgc::api::*;

// Simple linked list.
struct Foo(Option<Handle<Foo>>);

impl Traceable for Foo {
    fn trace_with(&self, tracer: &mut Tracer) {

impl Finalizer for Foo {
    fn finalize(&mut self) {

fn main() {
    let mut heap = cgc::heap::Heap::new(1024, 2048); // 1kb new space,2kb old space.
        let value = heap.allocate(Foo(None));
        let value2 = heap.allocate(Foo(Some(value.to_heap())));
        println!("{:?}", value2);
    heap.collect(); // value and value2 is GCed.


~57K SLoC