I'm merging many objects into a single vector containing render data (a mesh). This vector gets cleared and refilled on each frame (well, almost).
The issue is that clearing and then again reserving the vector size has a huge impact on performance in my case, because clear()
may also change the capacity.
In other words, I need to control when the capacity of the vector gets changed. I want to keep the old capacity for quite some time, until I decide myself that it's time to change it.
I see two options:
std::vector
is about to changeUpdate
In addition, what if for example a resize(10)
, and later a resize(5)
was called (just for illustration, multiply actual numbers by some millions)?
Will the later call to resize(5)
cause the vector to, maybe, reallocate?
The C++ function std::vector::resize() changes the size of vector. If n is smaller than current size then extra elements are destroyed. If n is greater than current container size then new elements are inserted at the end of vector.
Starting with C++11, we can call the vector::shrink_to_fit function after clear() , which reduces the vector's capacity to fir the size. It works by “requesting” a reallocation on the vector.
Resizing a vector doesn't destroy the values stored in the vector (except for those beyond the new size when shrinking, of course), however growing a vector beyond its capacity will copy (or, in C++11, move) them to a new place, thus invalidating and iterators, pointers or references to those elements.
To clear a vector and consume as little capacity as possible, use the swap trick: std::vector<T>(). swap(foo); This creates an empty vector, swaps its internals with foo , and then destroys the temporary vector, getting rid of the elements that once belonged to foo and leaving foo as if it was freshly created.
Actually the clear
member function keeps the vector capacity unchanged. It only destroys (calls the destructor) each of the vector elements and sets the vector size to 0.
In this situation, at each iteration, I would call clear()
to destroy all the vector elements, then call the member function reserve(size)
which, in the case where the vector capacity is too small, will increase it to at least size
.
This vector gets cleared and refilled on each frame (well, almost).
I would recommend a different approach.
Create a class that acts as a buffer for the rendering data.
If I am not mistaken, you never reduce the capacity of the buffer. You only increase its capacity when needed.
Make sure that class is an implementation detail and only instance is ever constructed.
Here's a skeletal implementation of what I am thinking.
namespace Impl_Detail
{
struct Buffer
{
size_t capacity;
size_t size;
std::vector<char> data;
// Pick whatever default capacity makes sense for your need.
Buffer(size_t cap = 100) : capacity_(cap), size_(0), data(cap) {}
void ensureCapacity(size_t cap)
{
if ( capacity_ < cap )
{
capacity_ = cap;
data.resize(capacity_);
}
}
// Add any other helpful member functions as needed.
};
// Create an instance and use it in the implementation.
Buffer theBuffer;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With