The Croc Programming Language
GC

Functions

uword_t croc_gc_maybeCollect (CrocThread *t)
 
uword_t croc_gc_collect (CrocThread *t)
 
uword_t croc_gc_collectFull (CrocThread *t)
 
uword_t croc_gc_setLimit (CrocThread *t, CrocGCLimit type, uword_t lim)
 
uword_t croc_gc_getLimit (CrocThread *t, CrocGCLimit type)
 

Detailed Description

Controlling the garbage collector.

Function Documentation

uword_t croc_gc_maybeCollect ( CrocThread t)

Runs a garbage collection cycle, but only if the VM decides it needs one.

uword_t croc_gc_collect ( CrocThread t)

Forces a garbage collection cycle.

uword_t croc_gc_collectFull ( CrocThread t)

Forces a full garbage collection cycle.

This will also scan reference cycles for garbage.

uword_t croc_gc_setLimit ( CrocThread t,
CrocGCLimit  type,
uword_t  lim 
)

Sets various limits used by the garbage collector.

Most have an effect on how often GC collections are run. You can set these limits to better suit your program, or to enforce certain behaviors, but setting them incorrectly can cause the GC to thrash, collecting way too often and hogging the CPU. Be careful.

Parameters
type

is the limit type to set. The values are as follows:

  • CrocGCLimit_NurseryLimit - The size, in bytes, of the nursery generation. Defaults to 512KB. Most objects are initially allocated in the nursery. When the nursery fills up (the number of bytes allocated exceeds this limit), a collection will be triggered. Setting the nursery limit higher will cause collections to run less often, but they will take longer to complete. Setting the nursery limit lower will put more pressure on the older generation as it will not give young objects a chance to die off, as they usually do. Setting the nursery limit to 0 will cause a collection to be triggered on every allocation. That's probably bad.
  • CrocGCLimit_MetadataLimit - The size, in bytes, of the GC metadata. Defaults to 128KB. The metadata includes two buffers: one keeps track of which old-generation objects have been modified; the other keeps track of which old- generation objects need to have their reference counts decreased. This is pretty low-level stuff, but generally speaking, the more object mutation your program has, the faster these buffers will fill up. When they do, a collection is triggered. Much like the nursery limit, setting this value higher will cause collections to occur less often but they will take longer. Setting it lower will put more pressure on the older generation, as it will tend to pull objects out of the nursery before they can have a chance to die off. Setting the metadata limit to 0 will cause a collection to be triggered on every mutation. That's also probably bad!
  • CrocGCLimit_NurserySizeCutoff - The maximum size, in bytes, of an object that can be allocated in the nursery. Defaults to 256. If an object is bigger than this, it will be allocated directly in the old generation instead. This avoids having large objects fill up the nursery and causing more collections than necessary. Chances are this won't happen too often, unless you're allocating really huge class instances. Setting this value to 0 will effectively turn the GC algorithm into a regular deferred reference counting GC, with only one generation. Maybe that'd be useful for you?
  • CrocGCLimit_CycleCollectInterval - Since the Croc reference implementation uses a form of reference counting to do garbage collection, it must detect cyclic garbage (which would otherwise never be freed). Cyclic garbage usually forms only a small part of all garbage, but ignoring it would cause memory leaks. In order to avoid that, the GC must occasionally run a separate cycle collection algorithm during the GC cycle. This is triggered when enough potential cyclic garbage is buffered (see the next limit type for that), or every n collections, whichever comes first. This limit is that n. It defaults to 50; that is, every 50 garbage collection cycles, a cycle collection will be forced, regardless of how much potential cyclic garbage has been buffered. Setting this limit to 0 will force a cycle collection at every GC cycle, which isn't that great for performance. Setting this limit very high will cause cycle collections only to be triggered if enough potential cyclic garbage is buffered, but it's then possible that that garbage can hang around until program end, wasting memory.
  • CrocGCLimit_CycleMetadataLimit - As explained above, the GC will buffer potential cyclic garbage during normal GC cycles, and then when a cycle collection is initiated, it will look at that buffered garbage and determine whether it really is garbage. This limit is similar to metadataLimit in that it measures the size of a buffer, and when that buffer size crosses this limit, a cycle collection is triggered. This defaults to 128KB. The more cyclic garbage your program produces, the faster this buffer will fill up. Note that Croc is somewhat smart about what it considers potential cyclic garbage; only objects whose reference counts decrease to a non-zero value are candidates for cycle collection. Of course, this is only a heuristic, and can have false positives, meaning non-cyclic objects (living or dead) can be scanned by the cycle collector as well. Thus the cycle collector must be run to reclaim ALL dead objects.

Parameters
limis the value of the limit.
Returns
the previous value of the limit that you set.
uword_t croc_gc_getLimit ( CrocThread t,
CrocGCLimit  type 
)

Gets GC limits as explained above.

Parameters
typeis the type of limit to get.
Returns
the current value of that limit.