Nim's Memory Management

Author:Andreas Rumpf

"The road to hell is paved with good intentions."

Multi-paradigm Memory Management Strategies

Nim offers multiple different memory management strategies. To choose the memory management strategy use the --mm: switch.

The recommended switch for newly written Nim code is `--mm:orc`.


--mm:orc is a memory management mode primarily based on reference counting. Cycles in the object graph are handled by a "cycle collector" which is based on "trial deletion". Since algorithms based on "tracing" are not used, the runtime behavior is oblivious to the involved heap sizes.

The reference counting operations (= "RC ops") do not use atomic instructions and do not have to -- instead entire subgraphs are moved between threads. The Nim compiler also aggressively optimizes away RC ops and exploits move semantics.

Nim performs a fair share of optimizations for ARC/ORC; you can inspect what it did to your time critical function via --expandArc:functionName.

--mm:arc uses the same mechanism as --mm:orc, but it leaves out the cycle collector. Both ARC and ORC offer deterministic performance for hard realtime systems, but ARC can be easier to reason about for people coming from Ada/C++/C -- roughly speaking the memory for a variable is freed when it goes "out of scope".

We generally advise you to use the acyclic annotation in order to optimize away the cycle collector's overhead but --mm:orc also produces more machine code than --mm:arc, so if you're on a target where code size matters and you know that your code does not produce cycles, you can use --mm:arc. Notice that the default async implementation produces cycles and leaks memory with --mm:arc, in other words, for async you need to use --mm:orc.

Other MM modes

Note: The default refc GC is incremental, thread-local and not "stop-the-world".
This is the default memory management strategy. It's a deferred reference counting based garbage collector with a simple Mark&Sweep backup GC in order to collect cycles. Heaps are thread-local. This document contains further information.
Simple Mark-And-Sweep based garbage collector. Heaps are thread-local.
Boehm based garbage collector, it offers a shared heap.
Go's garbage collector, useful for interoperability with Go. Offers a shared heap.
No memory management strategy nor a garbage collector. Allocated memory is simply never freed. You should use --mm:arc instead.

Here is a comparison of the different memory management modes:

Memory ManagementHeapReference CyclesStop-The-WorldCommand line switch
ORCSharedCycle CollectorNo--mm:orc
RefCLocalCycle CollectorNo--mm:refc
Mark & SweepLocalCycle CollectorNo--mm:markAndSweep
BoehmSharedCycle CollectorYes--mm:boehm
GoSharedCycle CollectorYes--mm:go

JavaScript's garbage collector is used for the JavaScript and NodeJS compilation targets. The NimScript target uses the memory management strategy built into the Nim compiler.