简体   繁体   中英

unordered_map Vs map Vs array - Memory analysis

As the title says, I would want to know the memory differences between unordered_map , map , and array .

Example:

unordered_map <long long , int> a;
map <long long , int> b;
long long c[1000000];

a and b have 1000000 stored elements.

I want to keep it as simple as possible. I searched on the internet and I didn't find a proper answer. I found that map and unordered_map use more memory than an array , but I don't know how to approach it.

EDIT: How to approach the memory differences, like if I store exact the same 2 elements, what are the memory differences.

Since C++11 the standard library containers support stateful allocators: you can pass an allocator type which records the amount of data allocated and track the maximum use. You'll need to also account for the object size as for an array there isn't really an allocator as the array is a built-in entity.

Here is an example:

#include <iostream>
#include <functional>
#include <memory>
#include <map>
#include <unordered_map>
#include <vector>

using namespace std;

static constexpr long total_size = 1000000;

template<typename T>
class CountingAllocator
{
public:
    shared_ptr<size_t> d_max = make_shared<size_t>(0u);
    using value_type = T;
    using pointer = T*;

    CountingAllocator() = default;
    template <typename S>
    CountingAllocator(CountingAllocator<S> const& other): d_max(other.d_max) {}
    size_t size() const { return *d_max; }
    T* allocate(size_t size) {
        size *= sizeof(T);
        *d_max += size;
        return reinterpret_cast<T*>(operator new(size));
    }
    void deallocate(void* ptr, size_t) {
        operator delete(ptr);
    }
    friend bool operator== (CountingAllocator const& c0, CountingAllocator const& c1) {
        return c0.d_max == c1.d_max;
    } 

    friend bool operator!= (CountingAllocator const& c0, CountingAllocator const& c1) {
        return !(c0 == c1);
    }
};

template <typename T>
void size(char const* name) {
    CountingAllocator<typename T::value_type> allocator;
    T m(allocator);
    for (int i = 0; i != total_size; ++i) {
        m[i] = i;
    }
    cout << name << "="  << allocator.size() << "\n";
}

int main() {
    size<map<long, long long, less<int>, CountingAllocator<pair<long const, long long>>>>("map");
    size<unordered_map<long, long long, hash<long>, equal_to<long>, CountingAllocator<pair<long const, long long>>>>("unordered_map");
    cout << "array=" << sizeof(long long[total_size]) << "\n";
    return 0;
}

With clang on ideone this prints (I aligned the sizes here, though):

map=          48000000
unordered_map=40654880
array=         8000000

The array has, of course, the smallest footprint (zero per element overhead). I'm surprised that the average per element overhead is smaller for unordered_map than for map . Using 5 words in addition to the data seems a bit excessive.

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