Подтвердить что ты не робот

Как я могу оценить использование памяти std:: map?

Например, у меня есть std:: map с известными sizeof (A) и sizeof (B), а карта содержит N записей внутри. Как вы оцениваете его использование памяти? Я бы сказал, что-то вроде

(sizeof(A) + sizeof(B)) * N * factor

Но каков фактор? Может быть, другая формула?

Может быть, проще запросить верхнюю границу?

4b9b3361

Ответ 1

Оценка будет ближе к

(sizeof(A) + sizeof(B) + ELEMENT_OVERHEAD) * N + CONTAINER_OVERHEAD

Для каждого добавляемого элемента есть накладные расходы, а также существует фиксированная накладная плата для поддержания структуры данных, используемой для структуры данных, хранящей карту. Обычно это двоичное дерево, например Red-Black Tree. Например, в реализации GCC С++ STL ELEMENT_OVERHEAD будет sizeof(_Rb_tree_node_base), а CONTAINER_OVERHEAD будет sizeof(_Rb_tree). На приведенном выше рисунке вы также должны добавить накладные расходы на структуры управления памятью, используемые для хранения элементов карты.

Вероятно, легче получить оценку, измеряя потребление памяти кода для различных больших коллекций.

Ответ 2

Вы можете использовать MemTrack, Curtis Bartley. Это распределитель памяти, который заменяет значение по умолчанию и может отслеживать использование памяти до типа выделения.

Пример вывода:

-----------------------
Memory Usage Statistics
-----------------------

allocated type                        blocks          bytes  
--------------                        ------          -----  
struct FHRDocPath::IndexedRec          11031  13.7% 2756600  45.8%
class FHRDocPath                       10734  13.3%  772848  12.8%
class FHRDocElemPropLst                13132  16.3%  420224   7.0%
struct FHRDocVDict::IndexedRec          3595   4.5%  370336   6.2%
struct FHRDocMDict::IndexedRec         13368  16.6%  208200   3.5%
class FHRDocObject *                      36   0.0%  172836   2.9%
struct FHRDocData::IndexedRec            890   1.1%  159880   2.7%
struct FHRDocLineTable::IndexedRec       408   0.5%  152824   2.5%
struct FHRDocMList::IndexedRec          2656   3.3%  119168   2.0%
class FHRDocMList                       1964   2.4%   62848   1.0%
class FHRDocVMpObj                      2096   2.6%   58688   1.0%
class FHRDocProcessColor                1259   1.6%   50360   0.8%
struct FHRDocTextBlok::IndexedRec        680   0.8%   48756   0.8%
class FHRDocUString                     1800   2.2%   43200   0.7%
class FHRDocGroup                        684   0.8%   41040   0.7%
class FHRDocObject * (__cdecl*)(void)     36   0.0%   39928   0.7%
class FHRDocXform                        516   0.6%   35088   0.6%
class FHRDocTextColumn                   403   0.5%   33852   0.6%
class FHRDocTString                      407   0.5%   29304   0.5%
struct FHRDocUString::IndexedRec        1800   2.2%   27904   0.5%

Ответ 3

Если вы действительно хотите знать промежуток времени памяти во время работы, используйте собственный распределитель и передайте его при создании карты. См. Книгу Джосуттиса и эту страницу (для пользовательского распределителя).

Может быть, проще запросить верхнюю границу?

Верхняя граница будет зависеть от точной реализации (например, конкретного варианта сбалансированного дерева). Может быть, вы можете сказать нам, почему вам нужна эта информация, чтобы мы могли лучше помочь?

Ответ 4

Мне недавно нужно было ответить на этот вопрос для себя и просто написал небольшую тестовую программу, используя std:: map, скомпилированную в MSVC 2012 в 64-разрядном режиме.

Карта с 150 миллионами узлов, пропитанных ~ 15 ГБ, что подразумевает 8-байтовый ключ с 8 байтами R, 8 байтов и 8 байтов, суммарно 32 байта, впитали около 2/3rds карта памяти для внутренних узлов, оставляя 1/3 для листьев.

Лично я обнаружил, что это удивительно плохая эффективность памяти, но это то, что есть.

Надеюсь, что это поможет в удобном правиле большого пальца.

PS: Накладные расходы std:: map - это один размер AFAICT node.

Ответ 5

Формула больше похожа:

(sizeof(A) + sizeof(B) + factor) * N

где коэффициент - накладные расходы. Карты С++ обычно реализуются как красно-черные деревья. Это двоичные деревья, поэтому для левого/правого узлов будет по крайней мере два указателя. Также будут некоторые элементы реализации - вероятно, указатель родителя и индикатор цвета, поэтому фактор может быть чем-то вроде

(sizeof( RBNode *) * 3 + 1) / 2

Однако все это сильно зависит от реализации - чтобы узнать, действительно ли вам нужно изучить код для своей собственной реализации библиотеки.

Ответ 6

Размер карты действительно зависит от реализации карты. Вы можете иметь разные размеры на разных компиляторах/платформах, в зависимости от того, какую реализацию STL они предоставляют.

Зачем вам этот размер?