Does it make sense to clear standard container instead of construct and destruct it?

Viewed 74

Let's say I have a function:

void someFunc(void) {

    std::vector<std::string> contentVector;

    // here are some operations on the vector
}

The function is called many times. And profiler shows hight percentage CPU usage of std::__u::vector::vector and std::__u::vector::~vector.

Does it make sense to create the vector outside of the function and call .clear() in the beginning of the functions?

The same question for other standard containers.

4 Answers

Does it make sense to clear standard container instead of construct and destruct it?

Yes, it can make sense. It depends on what you're doing. Use whatever is appropriate for the use case.

In case of vector, you would be reusing the storage which can be better in some use cases, so take that into consideration.

If you create the vector anew each time (as a local variable) then the vector will have to allocate a new internal array from the heap each time (and if you are adding items to the vector one-at-a-time without calling reserve() first, the vector may have to do several reallocations if its first allocated array(s) turn out not to be large enough to hold all of the items you want to add); then when your method-call returns, the vector's destructor will free the internally-allocated array from the heap to avoid a memory-leak.

If you keep the vector external to the method, on the other hand, then the vector's internal array will only have to be allocated once (with perhaps a few reallocations if you don't call reserve()), and the same internal array will be re-used after a call to clear() during future method-calls.

Doing it the second way will therefore cut down on CPU cycles used (no constant allocations and de-allocations from the heap, yay!), at the expense of using a keeping a chunk of additional RAM allocated the entire time (since the vector's internal array will stick around the entire time, and will be large enough to hold at least your worst-case-so-far number of items). Whether trading off RAM usage for CPU power is a worthwhile trade depends a lot on what you are doing, how much RAM your machine has, how much CPU power it has, and so on, so it's hard to say which is the better approach other than "try it both ways, measure performance, and pick the approach you prefer".

Does it make sense to create the vector outside of the function and call .clear() in the beginning of the functions?

Unless you assure there are no concurrent calls. If there are concurrent calls, hoisting variable outside the function would be a disaster.

Even there aren't. It might be a disaster once concurrency is introduced into this system.

To elaborate on the disaster: if this is a crawler function and reads different website. Using same variable outside the function will mix two websites' content into one.

My suggestion is leave local variable local. Unless contentVector is always holding the some data. Then the vector should be put somewhere else

This will depend very much on the situation.

Ideally, the caller should know as little as possible about how a function works (encapsulation). If the caller supplies the vector, you introduce the possibility of a bug if the caller passes the wrong vector. Also, you make changing the implementation of the function a painful maintenance burden. The more self-contained a function, the safer.

But performance may suffer and that is when you may compromise in performance critical sections - such as a tight loop. You can, though, have safe and fast versions of a function, where the safe version creates a vector and passes it to the fast version.

void some_function_fast_api(std::vector<std::string>& v) {

    // here are some operations on the vector
}

inline void some_function_safe_api() {

    std::vector<std::string> v;
    some_function_fast_api(v);
}
Related