简体   繁体   English

std :: deque内存使用 - Visual C ++,以及与其他人的比较

[英]std::deque memory usage - Visual C++, and comparison to others

Follow up to What the heque is going on with the memory overhead of std::deque? 跟进std :: deque的内存开销对heque的影响是什么?

Visual C++ manages deque blocks according to the container element type using this: Visual C ++使用以下方法根据容器元素类型管理deque块:

#define _DEQUESIZ   (sizeof (value_type) <= 1 ? 16 \
    : sizeof (value_type) <= 2 ? 8 \
    : sizeof (value_type) <= 4 ? 4 \
    : sizeof (value_type) <= 8 ? 2 \
    : 1)    /* elements per block (a power of 2) */

This results in very large memory footprint for small elements. 这导致小元件的内存占用非常大。 By changing the 16 in the first line to 128 I was able to drastically reduce the footprint required for a large deque<char> . 通过将第一行中的16更改为128,我能够大幅减少大型deque<char>所需的占用空间。 Process Explorer Private Bytes dropped from 181MB -> 113MB after 100m push_back(const char& mychar) calls). 在100m push_back(const char& mychar)调用之后,Process Explorer Private Bytes从181MB - > 113MB下降。

  • Can anybody justify the values in that #define ? 任何人都可以证明#define的值吗?
  • How do other compilers handle deque block sizing? 其他编译器如何处理deque块大小调整?
  • What would be their footprint (32-bit operation) for the simple test of 100m push_back calls to deque<char> ? 对于100m push_back调用deque<char>的简单测试,它们的占用空间(32位操作)是什么?
  • Does STL allow for overriding of this block size at compile-time, without modifying the <deque> code? STL是否允许在编译时覆盖此块大小,而不修改<deque>代码?

gcc has gcc有

return __size < 512 ? size_t(512 / __size) : size_t(1);

with a comment 评论

/*  The '512' is
 *  tunable (and no other code needs to change), but no investigation has
 *  been done since inheriting the SGI code.
 */

The Dinkumware (MS) implementation wants to grow the deque by 16-bytes at a time. Dinkumware(MS)实现希望一次增加16个字节的双端队列。 Could it be that this is just an extremely old implementation (like the first one ever?) that was tuned for platforms with very little memory (by today's standards) to prevent overallocating and exhausting memory (like a std::vector will do)? 难道这只是一个非常古老的实现(就像有史以来的第一个吗?),它被调整为具有极少内存(按照今天的标准)的平台,以防止过度分配和耗尽内存(就像std::vector一样)?

I had to implement my own queue in an application I'm working on because the 2.5X memory footprint of std::queue (which uses std::deque ) was unacceptable. 我必须在我正在处理的应用程序中实现自己的队列,因为std::queue (使用std::deque )的2.5倍内存占用是不可接受的。

There seems to be very little evidence on the interwebs that people have run into this inefficiency, which is surprising to me. 似乎很少有证据表明人们已经遇到这种低效率的互联网,这对我来说是令人惊讶的。 I would think such a fundamental data structure as a queue (standard library, no less) would be quite ubiquitous in the wild, and would be in performance/time/space-critical applications. 我认为这样一个基本的数据结构作为一个队列(标准库,不能少)在野外会非常普遍,并且会在性能/时间/空间关键应用程序中。 But here we are. 但我们在这里。

To answer the last question, the C++ standard does not define an interface to modify the block size. 要回答最后一个问题,C ++标准没有定义用于修改块大小的接口。 I'm pretty sure it doesn't mandate any implementation, just complexity requirements for insertions/removals at both ends. 我很确定它不强制要求任何实现,只是两端插入/删除的复杂性要求。

STLPort STLPort的

... seems to use : ...... 好像 用了

::: <stl/_alloc.h>
...
enum { _MAX_BYTES = 32 * sizeof(void*) };
...
::: <deque>
...
static size_t _S_buffer_size()
{
  const size_t blocksize = _MAX_BYTES;
  return (sizeof(_Tp) < blocksize ? (blocksize / sizeof(_Tp)) : 1);
}

So that would mean 32 x 4 = 128 bytes block size on 32bit and 32 x 8 = 256 bytes block size on 64 bit. 因此,这意味着32位上的32 x 4 = 128字节块大小,64位上的32 x 8 = 256字节块大小。

My thought: From a size overhead POV, I guess it would make sense for any implementation to operate with variable length blocks, but I think this would be extremely hard to get right with the constant time random access requirement of deque . 我的想法:从大小开销POV来看,我认为任何实现使用可变长度块都是有意义的,但我认为这对于deque的常量随机访问要求是非常困难的。

As for the question 至于问题

Does STL allow for overriding of this block size at compile-time, without modifying the code? STL是否允许在编译时覆盖此块大小而不修改代码?

Not possible here either. 这里也不可能。

Apache 阿帕奇

(seems to be the Rogue Wave STL version) apparently uses: (似乎是Rogue Wave STL版本)显然使用:

static size_type _C_bufsize () {
    // deque only uses __rw_new_capacity to retrieve the minimum
    // allocation amount; this may be specialized to provide a
    // customized minimum amount
    typedef deque<_TypeT, _Allocator> _RWDeque;
    return _RWSTD_NEW_CAPACITY (_RWDeque, (const _RWDeque*)0, 0);
}

so there seems to be some mechanism to override the block size via specialization and the definition of ... looks like this: 所以似乎有一些机制通过专业化覆盖块大小和...的定义如下所示:

// returns a suggested new capacity for a container needing more space
template <class _Container>
inline _RWSTD_CONTAINER_SIZE_TYPE
__rw_new_capacity (_RWSTD_CONTAINER_SIZE_TYPE __size, const _Container*)
{
    typedef _RWSTD_CONTAINER_SIZE_TYPE _RWSizeT;

    const _RWSizeT __ratio = _RWSizeT (  (_RWSTD_NEW_CAPACITY_RATIO << 10)
                                       / _RWSTD_RATIO_DIVIDER);

    const _RWSizeT __cap =   (__size >> 10) * __ratio
                           + (((__size & 0x3ff) * __ratio) >> 10);

    return (__size += _RWSTD_MINIMUM_NEW_CAPACITY) > __cap ? __size : __cap;
}

So I'd say it's, aehm, complicated. 所以我会说,这很复杂。

(If anyone feels like figuring this out further, feel free to edit my answer directly or just leave a comment.) (如果有人想要进一步解决这个问题,请随时直接编辑我的答案或只是发表评论。)

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

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