简体   繁体   中英

std::map vs unordered_map memory footprint for small N

For embedded system applications where memory usage is more of a concern than speed, what would be the best map container to use? std::map , std::unordered_map ? This would be for situations where N is less than, say, a hundred.

If implementation matters, then I'm concerned with the libstdc++ implementation (GCC).

While I understand that it's impossible to beat a simple array for memory usage, I want to avoid a data structure that has O(N) performance. So while I want to reduce memory footprint, I also want the lookup speed to be reasonable (better than O(N)). I don't care about other operations (insertions, removals), as they will occur infrequently.

If I wanted to make my own memory usage measurements, how would I go about doing this on a Linux platform?

Would boost::flat_map be suitable as an associative container with small footprint and lookup times better than O(n)?

For small N, a sorted vector is often the fastest container, and has minimal memory footprint. boost::flat_map is an implementation, others call it AssociativeVector. You can use std::lower_bound to implement it easily. Since the data has to be sorted, insert and delete operations are O(n) since the data has to be shifted in the vector.

With a sorted vector, you can do a binary search which is O(log N) for retrieval. The complexity of std::lower_bound is:

The number of comparisons performed is logarithmic in the distance between first and last (At most log2(last - first) + O(1) comparisons)

As an alternative my answer on vector , you could also consider a hash-map if you know the keys in advance. You could use gperf to generate a perfect hash function, and then have O(1) lookup. The real speed depends on the key type. I've seen cases where a std::map<string> outperformed a std::unordered_map<string> because the hash function for strings has to process the complete key string while the map comparison function often stops after the first few characters.

If speeds matters, implement both and benchmark. For heap profiling, I've used google perftools in the past.

If insertions and deletions occur infrequently, then instead of std::map or std::unordered_map , why not use a sorted std::vector and std::lower_bound or std::equal_range for lookup - you get ln(N) speed for the lookups and minimal space. boost::flat_map provides a nice associative container API that is implemented in precisely this way. Some detailed benchmarks are provides here and here . Another option would be an open-address hash-table. You'd have to do some experimenting to see whether this would satisfy your memory constraints and still give you faster lookup than ln(N) . Both solutions give good locality but if you want zero memory overhead and ln(N) is fast enough for lookups, then I'd go with the sorted array.

In addition to a sorted vector (like boost::flat_map ) you may also have a look at google::dense_hash_map , which is a hash map storing the data contiguously opposed to std::unordered_map , which allocates nodes separately. The price is the need for a dedicated empty key value and lack of iterator invalidation guarantees. There is also an even more compact google::sparse_hash_map (although slower).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM