11

I am a student of a system software faculty. Now I'm developing a memory manager for Windows. Here's my simple implementation of malloc() and free():

HANDLE heap = HeapCreate(0, 0, 0);

void* hmalloc(size_t size)
{
    return HeapAlloc(heap, 0, size);
}

void hfree(void* memory)
{
    HeapFree(heap, 0, memory);
}

int main()
{
    int* ptr1 = (int*)hmalloc(100*sizeof(int));
    int* ptr2 = (int*)hmalloc(100*sizeof(int));
    int* ptr3 = (int*)hmalloc(100*sizeof(int));

    hfree(ptr2);
    hfree(ptr3);
    hfree(ptr1);

    return 0;
}

It works fine. But I can't understand is there a reason to use multiple heaps? Well, I can allocate memory in the heap and get the address to an allocated memory chunk. But here I use ONE heap. Is there a reason to use multiple heaps? Maybe for multi-threaded/multi-process applications? Please explain.

Netherwire
  • 2,669
  • 3
  • 31
  • 54

5 Answers5

14

The main reason for using multiple heaps/custom allocators are for better memory control. Usually after lots of new/delete's the memory can get fragmented and loose performance for the application (also the app will consume more memory). Using the memory in a more controlled environment can reduce heap fragmentation.

Also another usage is for preventing memory leaks in the application, you could just free the entire heap you allocated and you don't need to bother with freeing all the object allocated there.

Another usage is for tightly allocated objects, if you have for example a list then you could allocate all the nodes in a smaller dedicated heap and the app will gain performance because there will be less cache misses when iterating the nodes.

Edit: memory management is however a hard topic and in some cases it is not done right. Andrei Alexandrescu had a talk at one point and he said that for some application replacing the custom allocator with the default one increased the performance of the application.

Raxvan
  • 6,257
  • 2
  • 25
  • 46
  • Are malloc/free usually automatically creates/frees heaps to reduce fragmentation? – Netherwire Nov 14 '13 at 18:04
  • You cannot just "delete the heap" - you can free it, but you ought not. delete uses the destructor (which is nothing for void* other than free) if you delete a huge swath you don't destroy the things in them, they may have pointers to other heaps if you've got container structures and such. He does say C++. – Alec Teal Nov 14 '13 at 18:06
  • 'preventing memory leaks' - that one is questionable –  Nov 14 '13 at 18:06
  • @Alec Teal i changed the 'delete' it was not appropriate there. @ Dieter Lücking Yes, it is done in games regularly, and not just small games , tripla A titles use techniques like this. – Raxvan Nov 14 '13 at 18:07
  • You still shouldn't just delete it, I think you are confusing allocators with regions. – Alec Teal Nov 14 '13 at 18:10
  • @Alec Teal you might be right, claptrap reply seems more appropriate for this question. – Raxvan Nov 14 '13 at 18:12
  • @AlecTeal 'preventing memory leaks' - it is ugly, at least (assuming all pointers allocated are not in use anymore) –  Nov 14 '13 at 18:13
  • @DieterLücking it cannot be used for memory management, please see my answer. – Alec Teal Nov 14 '13 at 18:17
  • @RomanChehowsky thanks fr reading my answer, I was worried it'd fall on deaf ears. Thanks and good luck – Alec Teal Nov 15 '13 at 14:12
5

This is a good link that elaborates on why you may need multiple heap: https://caligari.dartmouth.edu/doc/ibmcxx/en_US/doc/libref/concepts/cumemmng.htm

"Why Use Multiple Heaps?
Using a single runtime heap is fine for most programs. However, using multiple 
heaps can be more efficient and can help you improve your program's performance 
and reduce wasted memory for a number of reasons:

1- When you allocate from a single heap, you may end up with memory blocks on
   different pages of memory. For example, you might have a linked list that 
   allocates memory each time you add a node to the list. If you allocate memory for
   other data in between adding nodes, the memory blocks for the nodes could end up
   on many different pages. To access the data in the list, the system may have to 
   swap many pages, which can significantly slow your program.

   With multiple heaps, you can specify which heap you allocate from. For example, 
   you might create a heap specifically for the linked list. The list's memory blocks 
   and the data they contain would remain close together on fewer pages, reducing the 
   amount of swapping required.

 2- In multithread applications, only one thread can access the heap at a time to 
    ensure memory is safely allocated and freed. For example, say thread 1 is 
    allocating memory, and thread 2 has a call to free. Thread 2 must wait until 
    thread 1 has finished its allocation before it can access the heap. Again, this 
    can slow down performance, especially if your program does a lot of memory 
    operations.

    If you create a separate heap for each thread, you can allocate from them 
    concurrently, eliminating both the waiting period and the overhead required to 
    serialize access to the heap.


 3- With a single heap, you must explicitly free each block that you allocate. If you 
    have a linked list that allocates memory for each node, you have to traverse the 
    entire list and free each block individually, which can take some time.

    If you create a separate heap for that linked list, you can destroy it with a 
    single call and free all the memory at once.

  4- When you have only one heap, all components share it (including the IBM C and 
     C++ Compilers runtime library, vendor libraries, and your own code). If one 
     component corrupts the heap, another component might fail. You may have trouble 
     discovering the cause of the problem and where the heap was damaged.

     With multiple heaps, you can create a separate heap for each component, so if 
     one damages the heap (for example, by using a freed pointer), the others can 
     continue unaffected. You also know where to look to correct the problem."
mnabil
  • 695
  • 1
  • 5
  • 19
2

A reason would be the scenario that you need to execute a program internally e.g. running simulation code. By creating your own heap you could allow that heap to have execution rights which by default for security reasons is turned off. (Windows)

AndersK
  • 35,813
  • 6
  • 60
  • 86
2

You have some good thoughts and this'd work for C but in C++ you have destructors, it is VERY important they run.

You can think of all types as having constructors/destructors, just that logically "do nothing".

This is about allocators. See "The buddy algorithm" which uses powers of two to align and re-use stuff.

If I allocate 4 bytes somewhere, my allocator might allocate a 4kb section just for 4 byte allocations. That way I can fit 1024 4 byte things in the block, if I need more add another block and so forth.

Ask it for 4kb and it wont allocate that in the 4byte block, it might have a separate one for larger requests.

This means you can keep big things together. If I go 17 bytes then 13 bytes the 1 byte and the 13byte gets freed, I can only stick something in there of <=13 bytes.

Hence the buddy system and powers of 2, easy to do using lshifts, if I want a 2.5kb block, I allocate it as the smallest power of 2 that'll fit (4kb in this case) that way I can use the slot afterwards for <=4kb items.

This is not for garbage collection, this is just keeping things more compact and neat, using your own allocator can stop calls to the OS (depending on the default implementation of new and delete they might already do this for your compiler) and make new/delete very quick.

Heap-compacting is very different, you need a list of every pointer that points to your heap, or some way to traverse the entire memory graph (like spits Java) so when you move stuff round and "compact" it you can update everything that pointed to that thing to where it currently is.

Alec Teal
  • 5,770
  • 3
  • 23
  • 50
1

The only time I ever used more than one heap was when I wrote a program that would build a complicated data structure. It would have been non-trivial to free the data structure by walking through it and freeing the individual nodes, but luckily for me the program only needed the data structure temporarily (while it performed a particular operation), so I used a separate heap for the data structure so that when I no longer needed it, I could free it with one call to HeapDestroy.

Stuart
  • 1,428
  • 11
  • 20