代码之家  ›  专栏  ›  技术社区  ›  swegi

STL数据结构的内存使用,windows与linux

  •  11
  • swegi  · 技术社区  · 14 年前

    std::map . 在Windows下,Linux下使用的内存要多得多。有人知道为什么会这样吗?

    Linux: Last process took 42.31 s and used not more than 909 MB (RSS 900 MB) of memory

    窗户: Last process took 75.373 s and used not more than 1394 MB (RSS 1395 MB) of memory

    编辑: 很抱歉这么晚才回答问题。。。

    enum Symbol {
        ...
    }
    
    class GraphEntry {
    
        public:
    
        ...
    
        virtual void setAttribute (Symbol name, Value * value) = 0;
    
        const Value * attribute (Symbol name) const;
    
        private:
    
        std::map<Symbol, Attribute> m_attributes;
    };
    
    class Attribute {
    
        public:
    
        Attribute (Symbol name, Value * val);
    
        ...
    
        Symbol name () const;
    
        Value * valuePointer () const;
    
        void setValuePointer (Value * p);
    
        private:
    
        Symbol m_name;
    
        Value * m_value;
    };
    
    class Graph : public GraphEntry {
    
        ...
    
        public:
    
        Node * newNode (...);
    
        Graph * newSubGraph (...);
    
        Edge * newEdge (...);
    
        ...
    
        setSomeAttribute (int x);
    
        setSomeOtherAttribute (float f);
    
        ...
    
        private:
    
        std::vector<GraphEntry *> m_entries;
    };
    

    整个过程描述了一个图结构,它可以在节点和边上保存一些属性。 Value 只是基类,派生类可以保存具有任意类型的值,如 int std::string

    编辑2: -DRELEASE -DNDEBUG -DQT_NO_DEBUG -DQT_NO_DEBUG_OUTPUT -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DNOMINMAX /O2 /MD /Gy /EHsc

    编辑3: memuse ). 在Windows下,调用了一些WinAPI函数,但我不是这方面的专家,所以我只能这么说。

    编辑4: /GS- -D_SECURE_SCL 结果 Last process took 170.281 s and used not more than 1391 MB (RSS 1393 MB) of memory

    6 回复  |  直到 14 年前
        1
  •  8
  •   Matt Joiner    14 年前

    您将看到Windows上的内存使用量大约是它的1到2倍。除了堆算法,Windows malloc() ,以及随后通过 new std::map 的默认分配器类型的节点)与16个字节对齐。在Linux上, glibc defaults to 8 byte alignment . 假设由于碎片化、未使用页面的优化收获等原因,差异会变得不那么明显

    对代码的快速检查表明,映射键和值类型应分别为4和8字节( Symbol Attribute ). 在Linux上,这些字节最多为8个字节,在Windows上为16个字节。您应该有相同数量的映射节点,至少在MSVC实现中,这些节点看起来至少要占用22个字节,由于其成员对齐规则(这也是其malloc粒度),MSVC将扩展到32个字节。GCC将扩展到24,这意味着在MSVC到Gcc/Linux 32的总字节数大约为48字节。 每个节点 Windows上的内存使用量增加了大约50% .

    struct _Node
        {   // tree node
        _Nodeptr _Left; // left subtree, or smallest element if head
        _Nodeptr _Parent;   // parent, or root of tree if head
        _Nodeptr _Right;    // right subtree, or largest element if head
        value_type _Myval;  // the stored value, unused if head
        char _Color;    // _Red or _Black, _Black if head
        char _Isnil;    // true only if head (also nil) node
    

    我要补充的是,对于那些不熟悉内存使用方式的人,有几个因素在起作用:

    • 内存是以块的形式分配的,四舍五入到所使用的分配机制的下一个对齐倍数。对于堆来说 马洛克()
    • 虚拟内存由系统“提供”成块,称为页面,是帧大小的整数倍,这超出了本问题的范围。这对答案的影响很小,因为内存使用量与所讨论的页面大小(4K)相比非常大,而页面大小又与所使用的对齐方式(8和16)相比非常大。
        2
  •  7
  •   Matthieu M.    14 年前

    每个编译器都有自己的STL实现,因此您要比较:

    • GCC STL+Linux分配例程
    • VC++STL+Windows分配例程

    在这里很难进行有意义的比较,因为您不知道哪个分配例程或STL实现(或者可能两者都是)实际上是负责的。

    我想您并不是在比较32位程序和64位程序,因为这甚至没有意义。

        3
  •  6
  •   vobject    14 年前

    某些版本的VC++在发布版本中也使用检查迭代器(ySeCurysSCL)。 VC2005 VC2008 默认情况下打开它们。 by default

    根据编译器的不同,这可能是另一件要检查(并关闭)的事情。

        4
  •  0
  •   zvrba    14 年前

    在windows下是以发布模式还是调试模式执行测试?调试模式下的STL做了很多额外的检查;也许它还使用了更多的内存来执行所有的检查。

        5
  •  0
  •   Abyx    14 年前

    用于VC++尝试使用/GS命令行切换。

        6
  •  0
  •   yasouser    14 年前

    确保应用程序使用“new”或“malloc”或任何其他内存分配库调用分配的内存是使用“delete”或“free”或任何等效的库调用释放的。