简体   繁体   English

unordered_map Vs map Vs 数组——内存分析

[英]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 .正如标题所说,我想知道unordered_mapmaparray之间的内存差异。

Example:例子:

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

a and b have 1000000 stored elements. ab有 1000000 个存储元素。

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.我发现mapunordered_maparray使用更多的内存,但我不知道如何处理它。

EDIT: How to approach the memory differences, like if I store exact the same 2 elements, what are the memory differences.编辑:如何处理内存差异,比如如果我存储完全相同的 2 个元素,内存差异是什么。

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.由于 C++11 标准库容器支持有状态分配器:您可以传递一个分配器类型,它记录分配的数据量并跟踪最大使用量。 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):使用 ideone 上的 clang 打印出来(不过,我在这里对齐了尺寸):

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 .我很惊讶unordered_map每个元素的平均开销比map Using 5 words in addition to the data seems a bit excessive.除了数据之外使用 5 个字似乎有点过分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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