Grey Alien <gr**@andromeda.comwrites:
>Grey Alien <gr**@andromeda.comwrites:
>>>I am looking to write a very simple memory pool library to store only
one data type at a time
I missed this first time round. With only one size, avoiding free
will buy you a tiny amount more, but still unlikely to be enough to be
worth while.
Could you "flesh out" your example, a little more when you have a
chance, so that there is "enough there" that can form a basis on which
I build the library?.
Following on form the warning from Chris Dollin that there may be no
point in doing this, I have done some simple tests. Over a large
number of allocations and frees (with about 50-50 split of frees and
mallocs), chaining and unchaining the blocks buys you a tiny speed
advantage: about 2.8s vs 3.1s for a program doing 10,000,000 actions
(about 5,000,000 each of malloc and free). The test program is
dominated by the random sampling, not the allocation and freeing of
memory.[1]
In short, you are unlikely to get any significant advantage unless you
program does almost thing with the data. Do you know you will have a
speed problem? Are you writing a LISP virtual machine where
allocating and freeing CONS cells is about all it does? Do you know
that your system's malloc and free are particularly bad?
I did not spot your point of allocating only one size. In that case
you will get a shade more advantage since you will not need to test
any sizes, and the technique is simple enough that I may be worth
doing anyway, but it smacks of premature optimisation.
I would suggest you keep the allocations (and de-allocations) of your
special-sized objects separate, with their own functions (but which
just call malloc and free). That way it is simple to plug in special
allocator for these single-sized objects if you decide it might be
worth while (after measuring!).
I was going to say, come back if you want me to say more, but a
single-size free chain is so short I'll include it here (untested, not
even compiled):
struct alloc_block {
struct alloc_block *next;
};
static struct alloc_block *free_chain = NULL;
void *special_alloc()
{
void *p = free_chain;
if (p)
free_chain = free_chain->next;
else p = malloc(SPECIAL_ALLOC_SIZE);
return p;
}
void special_free(void *p)
{
struct alloc_block *block = p;
block->next = free_chain;
free_chain = block;
}
If your library can expose the type being allocated, then you don't
need to go via void *.
[1] This is one system, with one implementation of malloc/free (gcc
4.1.2 and glibc, in this case). There may be systems where you get
*worse* performance, or some with bad C libraries where it really pays
off.
--
Ben.