Сколько памяти занимает программа c

Обновлено: 05.07.2024

Мне нужно собрать статистику использования памяти в моей программе.

Мой код в основном написан с использованием STL.

Есть ли способ узнать, сколько памяти потребляется объектом STL?

Сколько памяти потребляется s1 и s2 ? Очевидно, что sizeof(string)+s1.length() не совсем точен.

ОТВЕТЫ

Ответ 1

Если вы хотите немного навязчиво, вы можете сделать собственный распределитель для отслеживания всего использования кучи по типу контейнера или по выделенному типу. Это довольно навязчиво, но довольно точно, для определения использования памяти. Это не отслеживает, сколько памяти занимает куча, хотя это сильно зависит от ОС.

0//это нуль, потому что строка не выделяла кучу пространства.
64
11

Ответ 2

Поскольку это полностью детали реализации, вы не можете определить это с точностью 100% .

Однако, как вы сказали, вы хотите поместить некоторый код в статистику использования памяти в своей программе, тогда вы можете сделать это с некоторой точностью.

Я считаю, что для std::string размер памяти, взятой строковыми объектами, будет почти равен:

Аналогично, для std::vector

Вы можете моделировать свою статистическую оценку по такой информации. Для вектора вы также можете рассмотреть размер T таким же образом, который заполнит . в приведенном выше уравнении. Например, если T - std::string , то:

И если T есть int , то

Надеюсь, такой анализ поможет вам вычислить размер с максимально возможной точностью.

Ответ 3

Просто для удовольствия я попытался найти использование памяти для отдельных строк, которые вы дали. Я согласен с людьми, которые говорят, что это принципиально невозможно; моя реализация не очень хороша во многих отношениях:

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

С учетом сказанного здесь мы идем:

Ответ 4

Я не думаю, что можно было бы измерить для отдельного контейнера.

Однако, чтобы получить общее резюме, вы можете использовать функцию mallinfo() (в Linux).

Если вы хотите узнать, где находятся самые большие в вашей программе памяти, вы можете запустить его под valgrind с помощью массива памяти профилировщика, который предоставит вам информацию, например, "15 МБ были выделены из map<my_data>. ", поэтому вы можете догадаться, насколько велики ваши структуры.

Ответ 5

Вы можете использовать Psapi для этого, если вы хотите использовать общую статистику использования памяти.

650 кб. При открытии файла сначала считываю конфигурацию в XmlDocument, затем считываю байты каждого элемента из файла в List<>, связывая их с соответствующим элементом из конфигурации (т.е. считал байты элемента, создал для него объект самописного класса Element, куда записал эти байты и ссылку на соответствующий элементу XmlNode узел из конфигурации, затем добавил этот объект в List<>). Всего считывается примерно 4 - 4.2 кк элементов (40 мб). Как мне кажется, приложение должно отъедать максимум 70-80 мб оперативки (файл + ссылки на узлы конфигурации), но на деле выходит 300+ мб (в релизе). Код вроде не сложный, оптимизировать некуда. В чем может быть проблема?

Оценить 1 комментарий

Если нашли решение, отпишитесь, пожалуйста, что именно было не так :) 1. List<> выделяет память кусками «про запас». Это называется capacity и отвечает за него одноимённое свойство. Если вы знаете, что ваш список в среднем будет содержать не больше N элементов, то это N нужно передать в соответствующий конструктор List<>.
2. Можно подсчитать байты и использовать выравнивание. Процесс трудоёмкий, но если сейчас много «пустого места», то в итоге вполне могут выйти желанные

80МБ.
3. Ну и упомянутые утечки памяти. GC.Collect и memory profiling вам в помощь.

А в чем проблема? Хотите точно знать сколько памяти будет использовать ваша программа - пишите на C.

Вы уверены что после разбора документа не остаются висеть какие-нибудь объекты? Может быть GC не отработал еще, может быть накладные расходы на маршалинг и прочее. Вообще как по мне не такой уж и большой оверхэд вышел.

Что значит «если хотите знать сколько памяти будет использовать»?! Языка со сборщиком мусорщика или работающие в песочнице в плане количества памяти отличаются только дополнительным расходами на вспомогательные объекты (сюда же кеширование и т.д.). Так что размер памяти всегда N+M, где N — реальное количество занятой памяти, а M — количество памяти занятое компонентами виртуальной машины. Во "взрослой" студии есть анализ памяти - ANALIZE - Launch Perfomance Wizzard.
Возможно, течет через замыкания. Или сборщик не поспевает, попробуйте GC.Collect().

Taraflex

Тут еще вопрос как именно вы определяете какой объем кушает прога?

Для проверки повставляй в каждом месте, которое выполняется больше 100 раз GC.Collect() и посмотри что получилось, если памяти съедать стал меньше значит где то не успевает собираться мусор. Потом можно по одному убирать то что повставлял и смотреть после какого память снова начала расти, в том месте и разбирайся, что то в нем не так.

Linux – довольно гибкая система, выполнить задачи в которой можно разными способами. Сегодня мы рассмотрим, как узнать, сколько оперативной памяти (ОЗУ — оперативное запоминающее устройство или RAM — Random Access Memory) используется определенным процессом. Сама оперативная память представляет собой специальное устройство, которое используется для временного хранения данных и обеспечивает функционирование ПО.

ОЗУ не стоит путать с ПЗУ (постоянным запоминающим устройством): их отличие заключается в том, что оперативная память является энергозависимой (при выключении компьютера все данные исчезнут), в то время как память жесткого диска сохранит все данные даже после выключения машины. Поэтому и функции, которые они выполняют, также разнятся. Процессор использует оперативную память для быстрого доступа к данным - жесткий диск такую скорость обеспечить не может, поэтому при запуске программа загружается в оперативную память.

Мы отследим занимаемую память на примере процесса веб-сервера Apache.

Команда ps

Первым вариантом будет команда ps, с помощью которой можно получить список процессов, запущенных на сервере.

<PID> - идентификатор процесса, в нашем случае это число 897110.

Получим следующий вывод:

ОЗУ будет представлено в процентном соотношении к общему количеству доступной памяти. К сожалению, в данном примере этот процент крайне мал, и столбец %MEM показывает 0,0.

Команда ps имеет свои ключи, которые вы также можете использовать для удобства:

  • -A : все процессы;
  • -a : процессы, связанные с конкретным терминалом, кроме главных системных процессов сеанса;
  • -d : все процессы, кроме главных системных процессов сеанса;
  • T : все процессы на конкретном терминале;
  • a : процессы, связанные с текущим терминалом, а также процессы других пользователей;
  • r : информация только о работающих процессах;
  • x : процессы, отсоединённые от терминала.

Команда top

Второй вариант – использование команды top. Более продвинутые пользователи должны знать эту команду, так как она выводит информацию о нагрузке системы и обновляет ее в реальном времени.

Обратите внимание на столбцы VIRT и %MEM. Последний столбец показывает информацию, которая очень похожа на ту, что получили предыдущей командой. А вот столбец VIRT отображает занятую виртуальную память.

Одним словом, виртуальная память – это некая комбинация ОЗУ и swap, которую использует запущенный процесс.

Обратите внимание, что команда top ограничена размерами окна, из-за чего игнорируется вся информация, которая не помещается на экран.

Получение занятой памяти из /proc

Последней командой для получения занятой процессором памяти будет обращение к псевдофайловой системе /proc.

Снова будет выведен результат, который схож с уже полученным ранее – виртуальная память, используемая процессом веб-сервера Apache.

Вот мы и разобрали на примере процесса Apache способы, которыми можно посмотреть занимаемую память.

Я разрабатываю приложение, в котором в настоящее время созданы сотни объектов.

можно ли определить (или приблизить) память, выделенную объектом (экземпляром класса)?

вы можете использовать профилировщик памяти, как

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

процесс широкий материал может быть получен, возможно, так

надеюсь, что это помогает ;)

на профилировщик памяти муравьев скажет вам точно, сколько выделяется для каждого объекта/способ/и т. д.

вот связанный пост где мы обсуждали определение размера ссылочных типов.

вы также можете использовать WinDbg и SOS или SOSEX (например, SOS с большим количеством команд и некоторыми существующими улучшенными) расширения WinDbg. Команда, которую вы будете использовать для анализа объекта по определенному адресу памяти !objsize

один очень важный пункт, чтобы помнить это !objsize дает только размер самого класса и не обязательно включает размер агрегатных объектов, содержащихся внутри класса - я понятия не имею, почему он не делает это так, как есть иногда это разочаровывает и вводит в заблуждение.

Я создал 2 предложения функций на веб-сайте Connect, которые просят включить эту возможность в VisualStudio. Пожалуйста, проголосуйте за пункты вы хотели бы видеть их добавлены как хорошо!

EDIT: Я добавляю следующее, чтобы уточнить некоторую информацию из ответа, предоставленного Чарльзом Бретаной:

  1. в ОП спросил о размере "объекта", а не "класса". Объект является экземпляром класса. Может, ты это имел в виду?
  2. память, выделенная для объекта, не включает JITted-код. Код JIT живет в своей собственной "куче кода JIT".
  3. JIT компилирует код только по методу на основе метода-не на уровне класса. Поэтому, если метод никогда не вызывается для класса, он никогда не компилируется JIT и, следовательно, никогда не имеет памяти, выделенной для него в коде JIT Куча.

в стороне, есть около 8 различных куч, которые CLR использует:

  1. куча загрузчика: содержит структуры CLR и тип system
  2. высокочастотная куча: статика, MethodTables, FieldDescs, карта интерфейса
  3. низкочастотная куча: EEClass, ClassLoader и таблицы поиска
  4. куча заглушек: заглушки для CAS, com-обертки, P/Invoke
  5. большая куча объектов: выделения памяти, требующие более 85k байты
  6. GC Heap: пользователь выделил память кучи частной для приложения
  7. куча кода JIT: память, выделенная mscoreee (механизм выполнения) и компилятором JIT для управляемого кода
  8. Process / Base Heap: взаимодействие/неуправляемые выделения, собственная память и т. д.

чтобы получить общее представление о распределении памяти в приложении, используйте следующую команду sos в WinDbg

обратите внимание, что !dumpheap дает только байты самого типа объекта и не включает байты любых других типов объектов, на которые он может ссылаться.

каждому "классу" требуется достаточно памяти для хранения всего его JIT-скомпилированного кода для всех его членов, которые были вызваны средой выполнения (хотя, если вы не вызываете метод в течение некоторого времени, среда CLR может освободить эту память и повторно jit ее снова, если вы вызовете ее снова. плюс достаточно памяти для хранения всех статических переменных, объявленных в классе. но эта память выделяется только один раз для каждого класса, независимо от того, сколько экземпляров класса, который вы создаете.

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

ссылочные переменные (ссылки на другие объекты) занимают 4 или 8 байт (32/64 бит ОС ?) int16, Int32, Int64 принимают 2,4, или 8 байт, соответственно.

строковая переменная занимает дополнительное хранилище для некоторых элементов метаданных (плюс размер указателя адреса)

кроме того, каждый ссылочная переменная в объекте также может рассматриваться как "косвенно" включающая память, занятую в куче объектом, на который она указывает, хотя вы, вероятно, захотите считать эту память принадлежащей этому объекту, а не переменной, которая ссылается на нее.

Если вы можете - сериализовать его!

существует академический вопрос каков размер объекта во время выполнения? и это интересно, но это может быть правильно ответил только профилировщик, который подключен к запущенному процессу. Я провел довольно много времени, глядя на это недавно и определил, что нет общего метода, который был бы точным и достаточно быстрым, чтобы вы когда-либо хотели использовать его в производственной системе. Простые случаи, такие как массивы числовых типов, имеют простые ответы, но за их пределами это лучший ответ будет Не пытайся разобраться. Зачем тебе это знать? Имеется ли другая информация, которая могла бы служить той же цели?

в моем случае я хотел ответить на этот вопрос, потому что у меня были различные данные, которые были полезны, но могли быть отброшены, чтобы освободить ОЗУ для более важных служб. Плакат "мальчики" являются Отменить Стек и кэш.

В Конце Концов Я пришел к выводу, что правильный способ управления размером стека отмены и кэша состоял в том, чтобы запросить объем доступной памяти (это 64-разрядный процесс, поэтому можно с уверенностью предположить, что все это доступно), а затем разрешить добавлять больше элементов, если есть достаточно большой буфер ОЗУ и требовать удаления элементов, если ОЗУ работает на низком уровне.

Читайте также: