|
| 1 | +Fooling around with memory allocation |
| 2 | +===================================== |
| 3 | + |
| 4 | +Memory allocation is one of those classically hard problems of computer |
| 5 | +science, or so I had been led to believe. So imagine my surprise when I came |
| 6 | +across a really simple elegant memory allocator as part of the FreeRTOS |
| 7 | +operating system. |
| 8 | + |
| 9 | +http://code.google.com/p/lumweb/source/browse/trunk/src/external/freeRTOS/Source/portable/MemMang/heap_2.c |
| 10 | + |
| 11 | +The free list is maintained as a linked list of blocks in order of increasing |
| 12 | +size. The malloc() function steps through them, looking for the first one |
| 13 | +large enough to accommodate a request. If the block is larger than the request |
| 14 | +by a sufficient margin, it is split into two blocks, the first one returned, |
| 15 | +and the second kept in the free list. When a block is freed, it is returned to |
| 16 | +the free list, retaining the ordering by block size. This is done by the |
| 17 | +prvInsertBlockIntoFreeList function. Each block begins with a struct |
| 18 | +containing the next-pointer for the size-ordered linked list, and a byte |
| 19 | +count. The allocation (the pointer returned by malloc) comes right after |
| 20 | +the struct. There are likely to be word alignment issues to think about, for |
| 21 | +example I am planning to use this on a 32-bit architecture so the smallest |
| 22 | +possible allocation would be four bytes. |
| 23 | + |
| 24 | +It's quite ingenious but it's prone to fragmentation. If you have lots of very |
| 25 | +small allocations they can chop the heap into small pieces, so that a later |
| 26 | +large allocation request is unnecessarily denied even though there is really |
| 27 | +enough free memory to serve it. |
| 28 | + |
| 29 | +I've got an idea for defragmentation which I will be tinkering with here. The |
| 30 | +idea is that when you free a block, you look at the immediately preceding and |
| 31 | +following blocks, not in order of increasing block size but in order of |
| 32 | +physical memory address, and you look to see, what is the largest contiguous |
| 33 | +block I can reassemble right now? If two or more blocks are contiguous (they |
| 34 | +have zero bytes between them) then they can be merged into one big block. |
| 35 | + |
| 36 | +A couple of minor details. The struct at the beginning of each block will need |
| 37 | +one more next-pointer for the ordering by physical address. The time spent in |
| 38 | +free() will be a little more, and during that time, any thread that might want |
| 39 | +to call malloc() or free() will need to be suspended (as is done in FreeRTOS |
| 40 | +already). |
| 41 | + |
| 42 | +I plan to try implementing this and writing some tests to see if it works as |
| 43 | +well as I hope. In particular it should be possible to do the worst-case thing |
| 44 | +above of many small allocations followed by one very large allocation. If it |
| 45 | +passes tests, I'll suggest it to the FreeRTOS folks as an alternative to |
| 46 | +heap_2.c. |
| 47 | + |
| 48 | +source: https://github.com/wware/stuff/tree/master/hack-malloc |
0 commit comments