I have a vector of pointers which I want to delete, but iterating over the vector and calling delete
for each element is quite slow. Is there a faster way?
Unfortunately I really need to store pointers, since I use a virtual superclass. Simplified, the class structure looks something like this:
class VirtualSuperClass
{
protected:
SomeType m_someMember;
// ...
public:
virtual void doSomething() = 0;
};
class Subclass_1 : public VirtualSuperClass
{
protected:
SomeType m_someSubclassMember;
// ...
public:
virtual void doSomething() { /* do something*/ }
};
class Subclass_2 : public VirtualSuperClass
{
protected:
SomeType m_someOtherSubclassMember;
// ...
public:
virtual void doSomething() { /* do something else*/ }
}
In my main method I fill a vector of pointers of the superclass and call the function doSomething()
for every element.
int main()
{
std::vector<VirtualSuperClass*> vec;
vec.push_back(new Subclass_1());
vec.push_back(new Subclass_2());
vec.push_back(new Subclass_2());
vec.push_back(new Subclass_1());
// and so on, about 40,000 elements (not really done with .push_back :) ) ...
// this actually runs in an application loop
for (size_t i = 0; i < vec.size(); i++)
{
vec[i]->doSomething();
}
// ...
for (size_t i = 0; i < vec.size(); i++)
{
delete vec[i]; // <-- pretty slow for large number of elements
vec[i] = NULL;
}
vec.clear();
return 0;
}
One thing you may be looking for is a custom allocator for the classes you allocate - this way you can effectively get and release memory to the system in bulk rather then in tiny fragments - it's probably the only solution for improving "overall" performance of this system without modifying it (which given your bottleneck sure looks like a good idea ;) ).
Any correct solution is going to boil down to doing a delete
on each pointer. Since you have profiled your code and identified that as being the bottleneck, then I would look for a solution that moves the delete
to another thread.
This could be done by:
- Create a worker thread that
delete
s pointers passed in
- Remove the pointers from the vector and copy them to another vector, owned by the worker thread
- Kick off the worker thread job, let it delete the pointers
This isn't going to be any faster than your current solution in terms of pure CPU time (and in fact can be slower depending on how you do it), but it will move the heavy lifting out of your main thread.
Another method that might improve performance is to use a kind of memory pool, in which you allocate one big raw buffer up front, and then placement-new
each individual object within that buffer.
This has the potential of improving performance because, although you still have to destroy each pointer, that destruction is done via calling the destructor directly rather than delete
ing it. This avoids having to go down to the system's memory manager, and that avoidance is where the potential lies for performance improvements.
There are significant caveats to this approach however, and I wouldn't recommend it in any but the most extreme cases. Among the caveats is the onerous responsibility you place on yourself to manage your own memory.