I am working at a quite speed dependend project.
This project should be written highly speedy and customizable.
This is why I really need nearly every milli second of execution time I can save.
Because of this I tend to use many news/deletes to not copy the objects themselves nor execute any kind of copy constructor.
To not overcall new/delete (because requesting Memory takes a huge time) I am saving already allocated memory in an internal pool of memory so I can reuse it later on.
I have got a class called "AllocationHelper", which contains some functions looking like the following one:
This code runs quite fast but when I searched for some bottlenecks in my program I stumbled over some quite strange behavior.
If I write my functions above like this:
My code suddenly runs 2x times faster.
I could not believe that my code is working correctly, so I tested all with std::cout to see what my program is doing and it worked like I wanted it to work:
It calls like 10 times the "new" operator and then calls around 1.000.000 times the push/pop operations.
If I remove this extern call to "_allocateVoidVector()" and insert the new in the if my code takes around 150ms for 1.000.000 iterations.
If I add this extern call and add "__attribute__((noinline))" (so gcc will not inline it) my code runs in 80ms.
This made me think about if the new is kind a called/prepared even if I not reach the else branch. After thinking and googling a while (without any results), I tried the exactly same code but this time used malloc:
"setUp" and "destroy" are my constructors and destructors (because they do not get called automatically with malloc and free). And again my code performed quite good, it took around 75ms with using malloc.
So my question is not really a question but more kind of:
This project should be written highly speedy and customizable.
This is why I really need nearly every milli second of execution time I can save.
Because of this I tend to use many news/deletes to not copy the objects themselves nor execute any kind of copy constructor.
To not overcall new/delete (because requesting Memory takes a huge time) I am saving already allocated memory in an internal pool of memory so I can reuse it later on.
I have got a class called "AllocationHelper", which contains some functions looking like the following one:
PHP Code:
std::vector<void*>* AllocationHelper::allocateVoidVector()
{
std::vector<void*>* ptr;
if(!allocatedVoidVectors.empty())
{
ptr=allocatedVoidVectors.back();
allocatedVoidVectors.pop_back();
}
else
{
ptr=new std::vector<void*>;
}
return ptr;
}
void AllocationHelper::recycleVoidVector(std::vector<void*>* ptr)
{
if(allocatedVoidVectors.size()<maximumPreAllocs)
{
ptr->clear();
allocatedVoidVectors.push_back(ptr);
return;
}
delete ptr;
}
This code runs quite fast but when I searched for some bottlenecks in my program I stumbled over some quite strange behavior.
If I write my functions above like this:
PHP Code:
__attribute__((noinline)) std::vector<void*>* AllocationHelper::_allocateVoidVector()
{
std::vector<void*>* ptr;
ptr=new std::vector<void*>;
return ptr;
}
std::vector<void*>* AllocationHelper::allocateVoidVector()
{
std::vector<void*>* ptr;
if(!allocatedVoidVectors.empty())
{
ptr=allocatedVoidVectors.back();
allocatedVoidVectors.pop_back();
}
else
{
ptr=_allocateVoidVector();
}
return ptr;
}
void AllocationHelper::recycleVoidVector(std::vector<void*>* ptr)
{
if(allocatedVoidVectors.size()<maximumPreAllocs)
{
ptr->clear();
allocatedVoidVectors.push_back(ptr);
return;
}
delete ptr;
}
I could not believe that my code is working correctly, so I tested all with std::cout to see what my program is doing and it worked like I wanted it to work:
It calls like 10 times the "new" operator and then calls around 1.000.000 times the push/pop operations.
If I remove this extern call to "_allocateVoidVector()" and insert the new in the if my code takes around 150ms for 1.000.000 iterations.
If I add this extern call and add "__attribute__((noinline))" (so gcc will not inline it) my code runs in 80ms.
This made me think about if the new is kind a called/prepared even if I not reach the else branch. After thinking and googling a while (without any results), I tried the exactly same code but this time used malloc:
PHP Code:
std::vector<void*>* AllocationHelper::allocateVoidVector()
{
std::vector<void*>* ptr;
if(!allocatedVoidVectors.empty())
{
ptr=allocatedVoidVectors.back();
allocatedVoidVectors.pop_back();
}
else
{
ptr=malloc(sizeof(std::vector<void*>));
ptr->setUp();
}
return ptr;
}
void AllocationHelper::recycleVoidVector(std::vector<void*>* ptr)
{
if(allocatedVoidVectors.size()<maximumPreAllocs)
{
ptr->clear();
allocatedVoidVectors.push_back(ptr);
return;
}
ptr->destroy();
free(ptr);
}
So my question is not really a question but more kind of:
Quote:
Did you ever encouter something similar (I am using MinGW with gcc 5.1.0)?
What do you suggest how should I solve this problem? Should I use extra functions (which also slows down a bit, but not too much) or should I use some kind of bad practice by allocating class objects with malloc?