Как я могу оценить использование памяти std:: map?
Например, у меня есть std:: map с известными sizeof (A) и sizeof (B), а карта содержит N записей внутри. Как вы оцениваете его использование памяти?
Я бы сказал, что-то вроде
(sizeof(A) + sizeof(B)) * N * factor
Но каков фактор? Может быть, другая формула?
Может быть, проще запросить верхнюю границу?
Ответы
Ответ 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 они предоставляют.
Зачем вам этот размер?