использование памяти структурами данных STL, Windows против Linux - PullRequest
11 голосов
/ 04 ноября 2010

У меня есть программа, которая интенсивно использует std::map. В Windows используется гораздо больше памяти, чем в Linux. Кто-нибудь знает, почему это происходит?

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

Windows: 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 ++ в командной строке с настройками выпуска.

EDIT: Извините за ответы на вопросы, которые поздно ...

Код выглядит так:

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: Под 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: Использование памяти считывается из файла / proc в linux (например, 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 ]

8 голосов
/ 15 ноября 2010

Вы заметите, что использование памяти в Windows где-то в 1-2 раза больше.За исключением алгоритмов кучи, Windows malloc() и впоследствии любые структуры данных, выделенные в куче через new (например, узлы std::map с типом распределителя по умолчанию), выровнены до 16 байтов.В Linux glibc по умолчанию имеет выравнивание 8 байтов .Предполагая некоторое сглаживание различий из-за фрагментации, оптимизации сбора неиспользуемых страниц и т. Д., Можно ожидать, что различия станут менее заметными

Быстрая проверка кода показывает, что ключ карты и типы значений должны составлять 4 и 8 байтов соответственно.(Symbol и Attribute).Они округляют до 8 байтов в Linux и до 16 байтов в Windows.У вас должно быть одинаковое количество узлов карты, по крайней мере, в реализации MSVC, они выглядят так, чтобы использовать как минимум 22 байта, которые MSVC увеличит до 32 из-за своих правил выравнивания членов, что также является его гранулярностью.GCC расширит его до 24, что означает приблизительное общее количество байтов в MSVC, равное 48, до GCC / Linux '32 на узел . Примерно на 50% больше использования памяти в Windows .

Вот структура узлов, используемая в 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() (если вы не перевернули обычную кучу или не использовали какой-либо другой распределитель, отличный от используемого по умолчанию).
  • Виртуальная память «предоставляется» системой порциями, известными как страницыцелочисленные кратные размеру кадра, что выходит за рамки этого вопроса.Это незначительно влияет на ответ, так как использование памяти настолько велико по сравнению с рассматриваемым размером страницы (4 КБ), а размер страницы, в свою очередь, настолько велик по сравнению с используемыми выравниваниями (8 и 16).
7 голосов
/ 04 ноября 2010

Каждый компилятор поставляется со своей собственной реализацией STL, поэтому вы сравниваете:

  • GCC STL + подпрограммы выделения Linux
  • VC ++ STL + Процедуры выделения Windows

Здесь довольно сложно провести содержательное сравнение, потому что вы не знаете, какая из процедур выделения или реализации STL (или, возможно, и того, и другого) на самом деле ответственна.

Полагаю, вы не сравниваете 32-битную программу с 64-битной, поскольку это было бы еще менее значимым.

6 голосов
/ 04 ноября 2010

Некоторые версии VC ++ также используют проверенные итераторы (_SECURE_SCL) в сборках выпуска. VC2005 и VC2008 включают их по умолчанию.VC2010 отключает их по умолчанию

В зависимости от вашего компилятора, это может быть еще одна вещь для проверки (и выключения).

0 голосов
/ 12 ноября 2010

Когда вы говорите, что используемая память «не более чем», вы имеете в виду пиковое использование памяти или среднее использование памяти за время существования приложения?

Убедитесь, что память, выделенная вашим приложением с использованием 'new' или 'malloc' или любым другим вызовом библиотеки выделения памяти, отменена с помощью 'delete' или 'free' или любым другим эквивалентным вызовом библиотеки.

В Linux вы можете использовать valgrind и проверять наличие утечек памяти.

0 голосов
/ 04 ноября 2010

Для VC ++ попробуйте использовать / GS- ключ командной строки.

0 голосов
/ 04 ноября 2010

Вы выполняли тест в режиме выпуска или отладки в Windows?STL в режиме отладки выполняет много дополнительных проверок;возможно, он также использует больше памяти для выполнения всех проверок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...