C++ Container performance question - c++

What would have better performance, a stl vector, or a dynamic array that's just realloc'd everytime I want to add something to it?
Would using vectors::iterator be faster then using a for loop on an array?
And if someone could explain why, that would be great.

Premature optimization is evil. The standard C++ way of doing things is to use the standard library containers as much as possible. If you want to use the best containers fitting your needs: here is the diagram
source: Original Image by Jameson Williams
One day you will maybe need to heavily optimize and use a dynamic array, but it should be rare.... one day you will also need collection that are multi-thread safe... and so on... but in general std containers are the way to go.

What would have better performance, a stl vector, or a dynamic array that's just realloc'd everytime I want to add something to it?
Stl vectors have insertion in amortized constant time (because reallocation is not done all the time and reservations occur by factor 1.5 (minimum)).
Therefore according to your description, vectors will be massively faster than reallocating all the time
Would using vectors::iterator be faster then using a for loop on an array?
In the general case: exactly identical.
However certain STL implementations generate checks in debug mode that can considerably slow down the use of container iterators.
(note most implementations implement vector/string iterators as a typedef to value_type*)
And if someone could explain why, that would be great.

What would have better performance, a stl vector, or a dynamic array that's just realloc'd everytime I want to add something to it?
stl vector should be the winner in this case, because it doesn't realloc every time[vector guarantees O(1) amortized insert time]. However, it might be similar if your malloc implementation is optimized for this kind of usage.
Would using vectors::iterator be faster then using a for loop on an array?
These should be the same, particularly because vector::iterator are usually just pointers into an array or thin wrappers thereof.

There is no difference in speed, but vector is massively safer. This is because the functions will just be inlined by your compiler, but vector carries a large number of exception and bounds-checking (if you ask for it) gurarantees that you won't see when using your own raw arrays.

Related

C++ alternatives to std::array when the size is fixed, but not a constexpr?

What is the best replacement for std::array<...> if I don't want to have to provide constexpr size? I figured it would be best to just use std::vector and do reserve(...) on it, but maybe I'm overlooking something?
std::vector should be the correct container of choice, if the size needs to be determined at runtime.
Yes, use std::vector.
So if your code is
std:array<int, 42> my_array;
Replace it by
std:vector<int> my_array(42);
Note: you probably don't want to use reserve, because it leaves the vector empty. If you are using std::array, your code doesn't have the concept of empty array, so it's best represented by a std::vector instance that is filled at construction, and never resized.
std::vector<> is probably your answer. I just wouldn't assume reserve() guarantees any speedup.
Bjarne Stroustrup:
People sometimes worry about the cost of std::vector growing
incrementally. I used to worry about that and used reserve() to
optimize the growth. After measuring my code and repeatedly having
trouble finding the performance benefits of reserve() in real
programs, I stopped using it except where it is needed to avoid
iterator invalidation (a rare case in my code). Again: measure before
you optimize.
http://www.stroustrup.com/bs_faq2.html [See bottom of "Why are the standard containers so slow?"]

Fast data structure that supports finding the minimum element and accessing, inserting, removing and updating data at any index

I'm looking for ideas to implement a templatized sequence container data structure which can beat the performance of std::vector in as many features as possible and potentially perform much faster. It should support the following:
Finding the minimum element (and returning it's index)
Insertion at any index
Removal at any index
Accessing and updating any element by index (via operator[])
What would be some good ways to implement such a structure in C++?
You generally be pretty sure that the STL implementations of all containers tend to be very good at the range of tasks they were designed for. That is to say, you're unlikely to be able to build a container that is as robust as std::vector and quicker for all applications. However, generally speaking, it is almost always possible to beat a generic tool when optimizing for a specific application.
First, let's think about what a vector actually is. You can think of it as a pointer to a c-style array, except that its elements are stored on the heap. Unlike a c array, it also provides a bunch of methods that make it a little bit more convenient to manipulate. But like a c-array, all of it's data is stored contiguously in memory, so lookups are extremely cheap, but changing its size may require the entire array to be shifted elsewhere in memory to make room for the new elements.
Here are some ideas for how you could do each of the things you're asking for better than a vanilla std::vector:
Finding the minimum element: Search is typically O(N) for many containers, and certainly for a vector (because you need to iterate through all elements to find the lowest). You can make it O(1), or very close to free, by simply keeping the smallest element at all times, and only updating it when the container is changed.
Insertion at any index: If your elements are small and there are not many, I wouldn't bother tinkering here, just do what the vector does and keep elements contiguously next to each other to keep lookups quick. If you have large elements, store pointers to the elements instead of the elements themselves (boost's stable vector will do this for you). Keep in mind that this make lookup more expensive, because you now need to dereference the pointer, so whether you want to do this will depend on your application. If you know the number of elements you are going to insert, std::vector provides the reserve method which preallocates some memory for you, but what it doesn't do is allow you to decide how the size of the allocated memory grows. So if your application warrants lots of push_back operations without enough information to intelligently call reserve, you might be able to beat the standard std::vector implementation by tailoring the growth function of your container to your particular needs. Another option is using a linked list (e.g. std::list), which will beat an std::vector in insertions for larger containers. However, the cost here is that lookup (see 4.) will now become vastly slower (O(N) instead of O(1) for vectors), so you're unlikely to want to go down this path unless you plan to do more insertions/erasures than lookups.
Removal at any index: Similar considerations as for 2.
Accessing and updating any element by index (via operator[]): The only way you can beat std::vector in this regard is by making sure your data is in the cache when you try to access it. This is because lookup for a vector is essentially an array lookup, which is really just some pointer arithmetic and a pointer dereference. If you don't access your vector often you might be able to squeeze out a few clock cycles by using a custom allocator (see boost pools) and placing your pool close to the stack pointer.
I stopped writing mainly because there are dozens of ways in which you could approach this problem.
At the end of the day, this is probably more of an exercise in teaching you that the implementation of std::vector is likely to be extremely efficient for most compilers. All of these suggestions are essentially micro-optimizations (which are the root of all evil), so please don't blindly apply these in important code, as they're highly likely to end up costing you a lot of time and headache.
However, that's not to say you shouldn't tinker and learn for yourself, so by all means go ahead and try to beat it for your application and let us know how you go! Good luck :)

Initializing a std::map when the size is known in advance

I would like to initialize a std::map. For now I am using ::insert but I feel I am wasting some computational time since I already know the size I want to allocate. Is there a way to allocate a fixed size map and then fill the map ?
No, the members of the map are internally stored in a tree structure. There is no way to build the tree until you know the keys and values that are to be stored.
The short answer is: yes, this is possible, but it's not trivial. You need to define a custom allocator for your map. The basic idea is that your custom allocator will set aside a single block of memory for the map. As the map requires new nodes, the allocator will simply assign them addresses within the pre-allocated block. Something like this:
std::map<KeyType, ValueType, std::less<KeyType>, MyAllocator> myMap;
myMap.get_allocator().reserve( nodeSize * numberOfNodes );
There are a number of issues you'll have to deal with, however.
First, you don't really know the size of each map node or how many allocations the map will perform. These are internal implementation details. You can experiment to find out, but you can't assume that the results will hold across different compilers (or even future versions of the same compiler). Therefore, you shouldn't worry about allocating a "fixed" size map. Rather, your goal should be to reduce the number of allocations required to a handful.
Second, this strategy becomes quite a bit more complex if you want to support deletion.
Third, don't forget memory alignment issues. The pointers your allocator returns must be properly aligned for the various types of objects the memory will store.
All that being said, before you try this, make sure it's necessary. Memory allocation can be very expensive, but you still shouldn't assume that it's a problem for your program. Measure to find out. You should also consider alternative strategies that more naturally allow pre-allocation. For example, a sorted list or a std::unordered_map.
Not sure if this answers your question, but Boost.Container has a flat_map in which you can reserve space. Basically you can see this as a sorted vector of (key, value) pairs. Tip: if you also know that your input is sorted, you can use insert with hint for maximal performance.
There are several good answers to this question already, but they miss some primary points.
Initialize the map directly
The map knows the size up front if initialized directly with iterators:
auto mymap = std::map(it_begin, it_end);
This is the best way to dodge the issue. If you are agnostic about the implementation, the map can then know the size up front from the iterators and you moved the issue to the std:: implementation to worry about.
Alternatively use insert with iterators instead, that is:
mymap.insert(it_begin, it_end);
See: https://en.cppreference.com/w/cpp/container/map/insert
Beware of Premature optimization
but I feel I am wasting some computational time.
This sounds a lot like you are optimization prematurely (meaning you do not know where the bottleneck is - you are guessing or seeing an issue that isn't really one). Instead, measure first and then do optimization - repeat if necessary.
Memory allocation could already be optimized, to a large degree
Rolling your own block allocator for the map could be close to fruitless. On modern system(here I include OS/hardware and the C++ language level) memory allocation is already very well optimized for the general case and you could be looking at little or no improvement if rolling your own block allocator. Even if you take a lot of care and get the map into one contiguous array - while an improvement in itself - you could still be facing the problem that in the end, the elements could be placed randomly in the array (eg. insertion order) and be less cache friendly anyway (this very much depending on your actual use case though - I'm assuming a super large data-set).
Use another container or third party map
If you are still facing this issue - the best approach is probably to use another container (eg. a sorted std::vector - use std::lower_bound for lookups) or use a third party map optimized for how you are using the map. A good example is flat_map from boost - see this answer.
Conclusion
Let the std::map worry about the issue.
When performance is the main issue: use a data structure (perhaps 3rd party) that best suits how your data is being used (random inserts or bulk inserts / mostly iteration or mostly lookups / etc.). You then need to profile and gather performance metrics to compare.
You are talking about block allocators. But it is hard to implement. Measure before think about such hard things. Anyway Boost has some articles about implementing block allocator. Or use already implemented preallocated map Stree

Compare between stl containers and arrays?

In which case using vectors or sets (stl containers ) is advantageous compared to normal arrays?
"Normal arrays" are static objects: Their size is fixed and determined at compile time. Dynamic containers can have an arbitrary amount of elements which can change at runtime.
Necessarily, dynamic containers have to use more expensive memory allocation operations than static arrays. If you need a dynamic container, there's no way around it, but if a static array suffices, you might prefer that (but use std::array!).
Note also that static arrays with automatic storage usually cannot be too large, since programs typically only have limited memory for automatic objects.
Another point is utility: Several advanced data structures like linked lists and binary search trees are only available in the standard library as dynamic containers. If you need list or a queue or a map, even if it's just small and of bounded size, the dynamic containers are readily available, while there is no static analogue as part of the standard library. (However, thanks to allocators used by the standard containers, you can always put a dynamic container inside a static array by using a pool-type allocator. C++ decouples object lifetime from memory lifetime.)
I suggest that there is almost never a reason to use std::vector. std::deque has all the advantages (constant time access, etc) with none of the drawbacks (terrible resize performance). The only time you would ever choose a vector over a deque is if you need the fact that it's backed by a real, old-fashioned, C-style array. And the only reason for that is if you need to pass it into some legacy function (as an array).
The advantages of vector over a traditional array are limited. It will grow if you insert past it's current size, but extremely inefficiently (see std::deque for a better option). It is just as easy to index past the end of a vector as it is an array, so no benefit there. The memory management quality is only such that it will allocate/deallocate items it contains. But these are typically pointers so that doesn't help. If they're instances (not pointer) then an array will also allocate/deallocate them properly too.
If I need an array, I would probably choose vector because it has some nice API things like size, begin, & end. But in general my suggestion is DON'T USE EITHER ONE! GO WITH std::deque INSTEAD!
One advantage is that STL containers take care of memory management for you and are less likely to result in buffer overflows or memory leaks than are C-style arrays. They're also prebuilt, so you don't have to spend time reinventing the wheel. So any time you're concerned about such things, STL containers are a better choice.
Advantageous in what way? set, multiset, vector, list, map, deque, stack, queue, priority_queue, multimap, bitset are all implemented differently. It depends on what you're doing. Some are implemented with a balanced tree, some with a contiguous array, some as linked lists, etc. Some are faster at inserting, some are faster at accessing, some work well with deleting, etc.
No container is always advantageous to another, or else the other wouldn't exist. Part of software development is being able to make decisions such as "which container should I use" so what's your real question, and how do you need your container to be advantageous?
Obviously, arrays will always be faster than vectors because the underlying component of a vector is an array, so the vector will just have overhead. But that overhead is doing a lot of wonderful things for you that means you don't have to worry about tons of things that you do have to worry about with arrays.
Most of the time the standard containers will be preferred over an old-fashioned array. They just have a lot more capabilities. The only time an array would be reasonable over std::vector would be when the size is known at compile time and is reasonably small (i.e. not megabytes) and you need to save the overhead of heap allocation. Sometimes an array is slightly more convenient as you can pass arr instead of &vec[0] to a function, but that's a very small price to pay.
If you're having trouble choosing between std::vector and std::set and the other standard containers, see here: In which scenario do I use a particular STL container?

Efficiency of iterators in unordered_map (C++)

I can't seem to find any information on this, so I turn to stackoverflow. How efficient are the iterators of std::tr1::unordered_map in C++? Especially compared to, say, list iterators. Would it make sense to make a wrapper class that also holds all the keys in a list to allow for efficient iteration (my code does use a lot of iteration over the keys in an unordered_map). For those who will recommend boost, I can't use it (for whatever reasons).
I haven't checked TR1, but N3035 (C++0x draft) says this:
All the categories of iterators
require only those functions that are
realizable for a given category in
constant time (amortized). Therefore,
requirement tables for the iterators
do not have a complexity column.
The standard isn't going to give an efficiency guarantee other than in terms of complexity, so you have no guaranteed comparison of list and unordered_map other than that they're both amortized constant time (i.e., linear time for a complete iteration over the container).
In practice, I'd expect an unordered_map iterator to be at least in the vicinity of list, unless your hashmap is very sparsely populated. There could be an O(number of buckets) term in the complexity of the complete iteration. But I've never looked at even one implementation specifically of unordered_map for C++, so I don't know what adornments to expect on a simplistic "array of linked lists" hashtable implementation. If you have a "typical" platform test it, if you're trying to write code that will definitely be the fastest possible on all C++ implementations then tough luck, you can't ;-)
The unordered_map iterator basically just has to walk over the internal tree structure of the hashtable. This just means doing some pointer following, and so should be pretty efficient. Of course, if you are walking an unordered_map a lot, you may be using the wrong data structure in the first place. In any case, the answer to this, as it is for all performance questions, is for you to time your specific code to see if it is fast enough.
Unfortunately, you can't say for sure if something is efficient enough unless you've tried it and measured the results. I can tell you that the standard library, TR1, and Boost classes have had tons of eyes on them. They're probably as fast as they're going to get for most common use cases. Walking an container is certainly a common use case.
With all that said, you need to ask yourself a few questions:
What's the clearest way to say what I want? It may be that writing a wrapper class adds unneeded complexity to your code. Make it correct first, then make it fast.
Can I afford the extra memory and time to maintain a list in parallel with the unordered_map?
Is unordered_map really the right data structure? If your most common use case is traversal from beginning to end, you might be better off with vector because the memory is guaranteed to be contiguous.
Answered by the benchmarks here https://stackoverflow.com/a/25027750/1085128
unordered_map is partway between vector and map for iteration. It is significantly faster than map.