Memory Management

From D Wiki
Revision as of 15:36, 7 March 2014 by Verax (talk | contribs) (Begin copying article from dlang.org)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Most non-trivial programs needs to allocate and free memory. Memory management techniques become more and more important as programs increase in complexity, size, and performance. D offers many options for managing memory.

The three primary methods for allocating memory in D are:

  • Static data, allocated in the default data segment.
  • Stack data, allocated on the CPU program stack.
  • Garbage collected data, allocated dynamically on the garbage collection heap.

The techniques for using them, as well as some advanced alternatives are:

  • Strings (and Array) Copy-on-Write
  • Real Time
  • Smooth Operation
  • Free Lists
  • Reference Counting
  • Explicit Class Instance Allocation
  • Mark/Release
  • RAII (Resource Acquisition Is Initialization)
  • Allocating Class Instances On The Stack
  • Allocating Uninitialized Arrays On The Stack
  • Interrupt Service Routines

Strings (and Array) Copy-on-Write

Consider the case of passing an array to a function, possibly modifying the contents of the array, and returning the modified array. As the contents of an array are accessed through a reference, a crucial issue is who owns the contents of the array? For example, a function to convert an array of characters to upper case:

char[] toupper(char[] s)
{
    int i;

    for (i = 0; i < s.length; i++)
    {
        char c = s[i];
        if ('a' <= c && c <= 'z')
            s[i] = cast(char)(c - ('a' - 'A'));
    }
    return s;
}

Note that the caller's version of s[] is also modified. This may be not at all what was intended, or worse, s[] may be a slice into a read-only section of memory.

If a copy of s[] was always made by toupper(), then that will unnecessarily consume time and memory for strings that are already all upper case.

The solution is to implement copy-on-write, which means that a copy is made only if the string needs to be modified. Some string processing languages do do this as the default behavior, but there is a huge cost to it. The string "abcdeF" will wind up being copied 5 times by the function. To get the maximum efficiency using the protocol, it'll have to be done explicitly in the code. Here's toupper() rewritten to implement copy-on-write in an efficient manner:

char[] toupper(char[] s)
{
    int changed;
    int i;

    changed = 0;
    for (i = 0; i < s.length; i++)
    {
        char c = s[i];
        if ('a' <= c && c <= 'z')
        {
            if (!changed)
            {
                char[] r = new char[s.length];
                r[] = s;
                s = r;
                changed = 1;
            }
            s[i] = cast(char)(c - ('a' - 'A'));
        }
    }
    return s;
}

Copy-on-write is the protocol implemented by array processing functions in the D Phobos runtime library.