Reputation: 28932
I have an STL container (std::list) that I am constantly reusing. By this I mean I
When profiling using callgrind I am seeing a large number of calls to new
(malloc
) and delete
(free
) which can be quite expensive. I am therefore looking for some way to preferably preallocate a reasonably large number of elements. I would also like my allocation pool to continue to increase until a high water mark is reach and for the allocation pool to continue to hang onto the memory until the container itself is deleted.
Unfortunately the standard allocator continually resizes the memory pool so I am looking for some allocator that will do the above without me having to write my own.
Does such an allocator exist and where can I find such an allocator?
I am working on both Linux using GCC and Android using the STLPort.
Edit: Placement new
is ok, what I want to minimize is heap walking which is expensive. I would also like all my object to be as close to eachother as possible to minimize cache misses.
Upvotes: 5
Views: 1017
Reputation: 68114
It sounds like you may be just using the wrong kind of container: With a list, each element occupies a separate chunk of memory, to allow individual inserts/deletes - so every addition/deletion form the list will require a separate new()/delete()
.
If you can use a std::vector
instead, then you can reserve
the required size before adding the items.
Also for deletion, it's usually best not to remove the items individually. Just call clear()
on the container to empty. it.
Edit: You've now made it clear in the comments that your 'remove the elements during processing' step is removing elements from the middle of the list and must not invalidate iterators, so switching to a vector is not suitable. I'll leave this answer for now (for the sake of the comment thread!)
Upvotes: 7
Reputation: 21418
The allocator boost::fast_pool_allocator
is designed for use with std::list
.
The documentation claims that "If you are seriously concerned about performance, use boost::fast_pool_allocator
when dealing with containers such as std::list
, and use boost::pool_allocator
when dealing with containers such as std::vector
."
Note that boost::fast_pool_allocator
is a singleton and by default it never frees allocated memory. However, it is implemented using boost::singleton_pool
and you can make it free memory by calling the static functions boost::singleton_pool::release_memory()
and boost::singleton_pool::purge_memory()
.
Upvotes: 6
Reputation: 16090
Comment was too short so I will post my thoughts as an answer.
IMO, new/delete can come only from two places in this context.
I believe std::list<T>
is implemented with some kind of nodes as normally lists are, for various reasons. Therefore, each insertion and removal of an element will have to result in new/delete of a node. Moreover, if the object of type T
has any allocations and deallocations in c'tor/d'tor, they will be called as well.
You can avoid recreation of standard stuff by reiterating over existing nodes instead of deleting them. You can use std::vector
and std::vector::reserve
or std::array
if you want to squeeze it to c-level.
Nonetheless, for every object created there must be called a destructor. The only way I see to avoid creations and destructions is to use T::operator=
when reiterating over container, or maybe some c++13 move
stuff if its suitable in your case.
Upvotes: -1
Reputation: 2247
You can try and benchmark your app with http://goog-perftools.sourceforge.net/doc/tcmalloc.html, I've seen some good improvements in some of my projects (no numbers at hand though, sorry)
EDIT: Seems the code/download has been moved there: http://code.google.com/p/gperftools/?redir=1
Upvotes: 0