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

时间:2010-11-04 10:17:19

标签: c++ stl memory-management

我有一个大量使用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

我在命令行上使用gcc 4.4.3和VS 2010 C ++编译器,具有发布设置。

编辑: 很抱歉回答迟到的问题......

代码如下所示:

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只是一个基类,派生类可以包含任意类型的值,例如intstd::string

编辑2: 在Windows下,我使用以下标志:-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: 从linux下的/ proc文件中读取内存使用情况(如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 个答案:

答案 0 :(得分:8)

您会发现Windows上的内存使用量大约是1到2倍。除了堆算法,Windows malloc()以及随后通过new在堆上分配的任何数据结构(例如具有默认分配器类型的std::map的节点)都与16个字节对齐。在Linux上,glibc defaults to 8 byte alignment。假设由于碎片,优化收获未使用的页面等而导致差异平滑,您可以预期差异将变得不那么明显

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

这是MSVC中使用的节点结构,如果您有兴趣,我可以查看GCC等效项:

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

我会为那些不熟悉内存使用情况的人添加内容,有几个因素在起作用:

  • 内存以块为单位进行分配,舍入到所使用的分配机制的下一个对齐倍数。对于堆,malloc()对齐规则正在使用中(除非您破坏通常的堆或使用除默认值之外的其他分配器)。
  • 虚拟内存由系统“提供”,称为页面,帧大小的整数倍,这超出了本问题的范围。这对答案影响很小,因为与所讨论的页面大小(4K)相比,内存使用量非常大,而且与使用中的对齐(8和16)相比,页面大小相当大。

答案 1 :(得分:7)

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

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

在此处绘制有意义的比较非常困难,因为您不知道哪个分配例程或STL实现(或可能两者)实际负责。

我认为你不是要将32位程序与64位程序进行比较,因为这样做的意义就更小了。

答案 2 :(得分:6)

某些版本的VC ++也在发布版本中使用了已检查的迭代器(_SECURE_SCL)。 VC2005VC2008默认启用它们。 VC2010禁用它们by default

根据您的编译器,这可能是检查(和关闭)的另一件事。

答案 3 :(得分:0)

您是否在Windows下以发布或调试模式执行测试?调试模式下的STL会进行大量额外检查;也许它还使用更多的内存来执行所有检查。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

当您说使用的内存是“不超过”时,您指的是应用程序生命周期内的峰值内存使用量或平均内存使用量吗?

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

在Linux中,您可以使用valgrind并检查内存泄漏。