============================================================================== CMM: a Customisable Memory Manager Authors: Giuseppe Attardi, Tito Flagella, Pietro Iglio Date: 26 October 95 Address: Giuseppe Attardi Dipartimento di Informatica Corso Italia 40 I-56125 Pisa, Italy e-mail: cmm@di.unipi.it ============================================================================== ============================================================================= | Table Of Contents ============================================================================= - Overview - Installation - User Guide for C++ - DefaultHeap - TempHeap - MarkAndSweep - User Guide for C - Detecting Memory Leaks - Environment Variables - Reporting Bugs - Contributors ============================================================================== | Overview ============================================================================== The CMM is a memory management facility supporting memory intensive applications in C++. The CMM can manage several heaps, each one implementing a different storage discipline. The default heap for collectable objects uses the technique of mostly copying garbage collection, providing good performance and memory compaction. Other available heaps are a temporary heap, and a mark&sweep heap. CMM users can define their own heap classes for the specific storage requirements of their algorithms. CMM has been tested on: - SunOS 4.x - Solaris 2.x - Linux 1.x - AIX (RS6000) - SGI but it should run without changes also on HPUX, NeXTOS and DOS (djgpp). If you are interest in some other platforms you can send mail to cmm@di.unipi.it. ============================================================================== | Installation ============================================================================== The latest distribution of CMM is available via anonymous ftp from: ftp.di.unipi.it:/pub/project/posso/cmm as a compressed (gzip) tar file. Once you have obtained the distribution, you should extract its content with the command: zcat cmm-XX.tar | tar xf - This will create the directory 'cmm'. Enter that directory and type: > make This will create a library file libCmm.a. Typing: > make test will run a few test programs to test the library. ============================================================================== | Quick Guide for C++ ============================================================================== CMM provides two abstract classes, CmmHeap and CmmObject. The available heaps are DefaultHeap, TempHeap, MarkAndSweep. More complete documentation on the CMM is available in directory cmm/doc. Programs using CMM must include the file cmm.h and link libCmm.a in the executable. When creating a collected object one can specify in which heap to allocate it, by supplying a heap parameter to the new operator, e.g.: p = new(heap) Person(name, age); If no heap parameter is supplied, the objects are allocated in the heap specified by variable Cmm::heap, which by default has value Cmm::theDefaultHeap. DefaultHeap ------------------------------------------------------------------------------ The DefaultHeap implements a mostly-copying collector: live objects are copied and compacted except those pointed by ambiguous roots. This approach is convenient for reducing fragmentation and swapping. The drawback is that the user must supply information about the structure of objects and the overhead for the copy. Classes allocated in the DefaultHeap must be derived from class CmmObject. A method traverse() must be supplied by the programmer for each such collected class which contains pointers to other collected objects. The collector applies method traverse() to an object to find other objects to which it points. See file cmm.h for details. TempHeap ------------------------------------------------------------------------------ This heap is useful when a phase of a program allocates large amounts of temporary objects which are discarded at the end of the phase. A TempHeap is created with the instruction: tempHeap = new TempHeap(size); At the beginning of the phase, the program can switch to the tempHeap and clear it at the end of the phase, as follows: CmmHeap =previousHeap = CmmHeap::heap; // save the current heap CmmHeap::heap = tempHeap; // set the current heap to tempHeap ... program phase CmmHeap::heap = previousHeap; // restore the previous heap ... copy out of tempHeap any object which must survive tempHeap->clear(); // empty the tempHeap MarkAndSweep ------------------------------------------------------------------------------ This collector is fully conservative, so there is no need to supply information about objects layout. It does not perform compaction, therefore it may be subject to fragmentation and it may retain more objects than necessary. If you want automatic reclaimation for instances of a class `A' you must declare `A' as a subclass of CmmObject. Read the CMM documentation for more details. Once you declare class `A' as a subclass of CmmObject, every usage of new and delete operators will automatically use the MSW memory manager. No explicit initialization of the collector is needed and MSW_Automatic is the default. You can override the default with a statement: Cmm::heap = new MarkAndSweep(MSW_OnDemand); before using any other MSW function. The collector can be called explictly with: Cmm::heap->collect(); This is the only way to activate the collector if you use the MSW_OnDemand flag, otherwise the collector is automatically activated when the heap is full. ============================================================================== | Quick Guide for C ============================================================================== Currently only the MarkAndSweep heap provides a C interface. Since it is based on a fully conservative approach, there is no need to supply information about the objects layout. The "msw.h" file must be included at the top of every C file that uses the allocator. The memory manager must be initialized. Such task is performed calling: MswInit(); before using any other function provided by MSW. can be: - MSW_Automatic (the collector is automatically invoked when needed) - MSW_OnDemand (the collector is manually invoked by the user program) Once the collector has been initialized, you can use: void * mswAlloc (size_t size); to allocate a memory object void mswFree (void * obj); to release a memory object void * mswRealloc (void * obj, size_t size); to resize a memory object The behaviour of those functions is similar to the behaviour of malloc, free, realloc. The main difference is that, while a memory object allocated with malloc() can be only released calling free(), with MSW memory objects allocated with mswAlloc() can also be reclaimed automatically. Explicit deallocation of memory when no more need will delay the call to the collector when using the MSW_Automatic flag. For time-critical applications one can use: void * mswAllocOpaque (size_t size); in the case you ensure that the allocated object will not contain pointers inside (e.g. strings). This way such objects will not be traversed during the collection, speeding-up the sweep phase and reducing the amount of ambigous pointers traversed by the collector. If the collector has been initialized with the MSW_Automatic flag, then the collector is invoked automatically as soon the memory is low. It can also be called explicitly with: void mswCollect (void); This is the only way to invoke the collector if MSW has been initialized with the MSW_OnDemand flag. ============================================================================== | Detecting Memory Leaks ============================================================================== MSW includes a useful memory leaks detector that checks internal heap tables for corruption. You can enable memory leaks detection compiling the MSW with the macro MSW_CHECK_HEAP defined and not defining the NDEBUG macro. The heap is checked before and after every collection. You can place explicit calls to the heap-checker in any `suspect' place using: mswCheckHeap(); If is not 0, then you will get some output when the heap is checked. ============================================================================== | Environment Variables ============================================================================== Collector performance can be tuned using the following environment variables: CMM_MINHEAP initial heap size CMM_MAXHEAP maximum heap size CMM_INCHEAP increment size CMM_GENERATIONAL enable generational copying collector CMM_INCPERCENT expand threshold CMM_GCTHRESHOLD minimum amount of memory allocated before the MarkAndSweep collector is called Full description of these flags is in file cmm.h. ============================================================================== | Reporting Bugs ============================================================================== Bugs, suggestions and comments can be sent to cmm@di.unipi.it. When reporting a bug, please report the version number of the collector you are using and - possibily - the complete source of the code showing the bug. ============================================================================== | Contributors ============================================================================== The following people have contributed to this work: Giuseppe Attardi, attardi@di.unipi.it Tito Flagella, tito@di.unipi.it Pietro Iglio, iglio@di.unipi.it Carlo Traverso and John Abbott contributed useful hints. Joachim Hollman gave precious feedback on the first implementation of CMM.