Как узнать сколько памяти потребляет программа на c
Я разрабатываю Graph-класс на основе библиотеки boost-graph.
Объект Graph содержит буст-граф, так сказать adjacency_list, и карту. При мониторинге общего использования памяти моей программой, она потребляет довольно много (проверено с помощью pmap).
Теперь я хотел бы знать, сколько именно памяти занято заполненным объектом этого класса Graph? С заполненным я имею в виду, когда adjacency_list заполнен вершинами и ребрами.
Я обнаружил, что использование sizeof () меня далеко не уведет. Использование valgrind также не является альтернативой, поскольку ранее было выделено некоторое количество памяти, и это делает использование valgrind для этой цели непрактичным. Меня также не интересует, какие другие части программы стоят в памяти, я хочу сосредоточиться на одном единственном объекте.
Размер памяти (след) класса C ++ может быть недоступен в случаях, когда члены содержат указатели или контейнеры. Классу необходимо указать размер этих элементов или элементов, на которые они указывают. Если вас интересует размер экземпляра, вы всегда можете написать метод, который возвращает размер.
Извините, я должен был пояснить. На самом деле меня интересует общее использование памяти экземпляром объекта. В своем коде я создаю график и напрямую заполняю его некоторой информацией. И тогда я хочу знать, насколько «большой» этот экземпляр находится в памяти.
3 ответа
Я никогда не использовал adjacency_list , поэтому это всего лишь идея , хотя она работает с контейнерами STL.
Итак, using adjacency_list говорит BGL uses containers from the STL such as std::vector, std::list, and std::set to represent the set of vertices and the adjacency structure . Хорошо, тогда вам просто нужно предоставить смежный список std :: vector, std :: list и std :: set, которые имеют свой собственный тип распределителя. Добавить собственный распределитель в контейнеры STL очень просто. задача. Сделав все это, вам просто нужно получить от ваших распределителей размер памяти, который был выделен при заполнении adjacency_list.
Итак, идея состоит в том, чтобы построить смежный список из контейнеров STL (что кажется возможным после беглого просмотра документации BGL), которые имеют собственные типы распределителей.
Обновление 1 На самом деле вы не сказали, зачем вам нужно знать, сколько байтов потребляет ваш график. Если вам просто нужно получить это число только один раз, вам, вероятно, придется написать программу с заполнением графика и без него. Затем запустите, например, UNIX95= ps -u $USER -o vsz,args и найдите разницу. Примерно вы получите размер вашего графика.
Если вам нужно регулярно получать эти значения в вашем приложении и если вы не можете реализовать все решение с использованием распределителей, вам нужно начать с нескольких небольших шагов.
- Читайте о распределителях: Стандартный распределитель C ++, введение и реализацияРаспределители (STL)
- Попробуйте реализовать std :: vector с вашим собственным распределителем в качестве упражнения
- Попробуйте добавить счетные байты в свой распределитель
- Попробуйте построить график Boost с распределителем Настройка хранилища списка смежности
- Сделайте что-нибудь для подсчета байтов в членах std :: string ваших контейнеров. По умолчанию они не будут использовать распределитель своего контейнера. Поэтому либо вместо этого используйте строки фиксированного размера, либо каким-то образом управляйте вставкой распределителя контейнера в элементы этой строки. Опять же, взгляните на Добавление собственного распределителя в контейнеры STL
Кстати, если вы не хотите заново изобретать распределитель C ++, вы можете просто использовать что-то вроде этого:
Я понимаю, что вы хотите там сказать, в целом, но пока не могу воплотить это в жизнь. Я никогда не касался этой темы, и поэтому мне понадобится полный пример, который также объясняет, как фактически подсчитывается выделенная память.
С помощью встроенного в отладчик средства диагностики Использование памяти вы сможете находить утечки памяти и выявлять ее неэффективное использование. С помощью средства "Использование памяти" можно сделать один или несколько снимков управляемой и собственной памяти в куче, чтобы понять влияние использования памяти типов объектов. Анализировать использование памяти также можно без подключения отладчика — нужно просто указать выполняющееся приложение. Дополнительные сведения см. в разделе Запуск средств профилирования с отладчиком или без него. Сведения о выборе необходимого средства анализа памяти см. в разделе Выбор инструмента для анализа памяти.
Хотя с помощью средства Использование памяти можно делать снимки памяти в любой момент, для управления выполнением приложения во время анализа ошибок производительности вы можете использовать отладчик Visual Studio. Задание точек останова, пошаговое выполнение, всеобщее прерывание и другие действия отладчика могут помочь вам сосредоточиться на анализе производительности при обращении к наиболее важным ветвям кода. Выполняя эти действия, когда приложение запущено, вы сможете исключить влияние не интересующего вас кода и значительно ускорить диагностику проблем.
В этом руководстве рассмотрены следующие задачи:
- Создание моментальных снимков с данными об использовании памяти
- Анализ данных использования памяти
Если средство Использование памяти не предоставляет необходимые данные, можно воспользоваться другими средствами профилирования в Профилировщике производительности, предоставляющими другие виды информации, которая может оказаться полезной. Как правило, проблемы производительности приложения могут вызываться другими компонентами помимо памяти, такими как ЦП, отрисовка пользовательского интерфейса или время запроса сети.
Поддержка пользовательского распределителя. Профилировщик внутренней памяти работает путем сбора данных событий ETW выделения памяти, создаваемых во время выполнения. Распределители в CRT и пакете Windows SDK аннотированы на уровне исходного кода, что позволяет регистрировать их данные выделения. Если вы создаете собственные распределители, любые функции, возвращающие указатель на только что выделенную память в куче, можно декорировать с использованием __declspec(allocator), как показано в этом примере для myMalloc:
__declspec(allocator) void* myMalloc(size_t size)
Сбор данных об использовании памяти
Откройте проект для отладки в Visual Studio и установите точку останова в приложении в точке, где вы хотите начать проверку использования памяти.
Если вы подозреваете, что в определенной области памяти может возникнуть проблема, задайте первую точку останова до ее возникновения.
Так как из-за изменений в объеме выделяемой памяти создание профиля памяти для интересующей вас операции может быть затруднительно, разместите точки останова в начале и в конце операции или пройдите по ней, чтобы попробовать найти точку, в которой объем памяти изменился.
Установите вторую точку останова в конце функции или области кода, который требуется проанализировать, либо после возникновения предполагаемой проблемы с памятью.
Окно Средства диагностики появится автоматически, если вы не отключали эту функцию. Чтобы снова открыть окно, щелкните Отладка > Окна > Показать средства диагностики.
На панели инструментов выберите Использование памяти, применяя параметр Выбор средств.
Щелкните Отладка | Начать отладку (Запустить на панели инструментов или F5).
По завершении загрузки приложения отображается представление "Сводка" средств диагностики.
Поскольку сбор данных об использовании памяти может повлиять на производительность отладки приложений, основанных на машинном коде, а также смешанных программ, по умолчанию снимки памяти выключены. Чтобы включить моментальные снимки для приложений на базе машинного кода или для смешанных программ, начните сеанс отладки (клавиша: F5). Когда отобразится окно Средства диагностики, перейдите на вкладку Использование памяти и выберите Профилирование кучи.
Остановите (сочетание клавиш: SHIFT+F5) и перезапустите отладку.
Поскольку сбор данных об использовании памяти может повлиять на производительность отладки приложений, основанных на машинном коде, а также смешанных программ, по умолчанию снимки памяти выключены. Чтобы включить моментальные снимки для приложений на базе машинного кода или для смешанных программ, начните сеанс отладки (клавиша: F5). Когда отобразится окно Средства диагностики, перейдите на вкладку Использование памяти и выберите Профилирование кучи.
Остановите (сочетание клавиш: SHIFT+F5) и перезапустите отладку.
Чтобы сделать моментальный снимок в начале сеанса отладки, на сокращенной панели инструментов Использование памяти выберите команду Сделать снимок. (Таким образом здесь также можно задать точку останова.)
Чтобы получить базовые показатели для сравнения состояния памяти, сделайте снимок в начале сеанса отладки.
Запустите сценарий, который вызвал срабатывание первой точки останова.
После приостановки отладчика на первой точке останова на сокращенной панели инструментов Использование памяти выберите команду Сделать снимок.
Нажмите клавишу F5, чтобы запустить приложение до второй точки останова.
Теперь создайте еще один моментальный снимок.
На этом этапе можно начать анализировать данные.
Анализ данных использования памяти
В строках сводной таблицы "Использование памяти" приводятся моментальные снимки, сделанные во время сеанса отладки, и ссылки на дополнительные подробные представления.
Если сделать несколько снимков, в каждой строке сводной таблицы будет отображаться разница значений с предыдущим снимком.
Чтобы выполнить анализ данных об использовании памяти, щелкните одну из ссылок, которая позволяет открыть подробный отчет об использовании памяти:
- Чтобы отобразить подробности об изменении текущего моментального снимка по сравнению с предыдущим, щелкните ссылку разницы слева от стрелки (). Красная стрелка обозначает, что объем используемой памяти увеличился, а зеленая — что он снизился.
Чтобы быстрее выявить проблемы с памятью, типы объектов в отчетах об изменениях можно отсортировать по наибольшему увеличению общего объема (щелкните ссылку "Изменения" в столбце Объекты (разн.) ) или по наибольшему увеличению размера кучи (щелкните ссылку "Изменения" в столбце Размер кучи (разн.) ).
Чтобы отобразить подробности только для выбранного моментального снимка, щелкните ссылку "Без изменений".
Отчет отображается в новом окне.
Отчеты об управляемых типах
Щелкните текущую ссылку в ячейке Объекты (разн.) или Выделения (разн.) в сводной таблице "Использование памяти".
В дереве Объекты, на которые указывает ссылка отображаются ссылки, активные для выбранного в верхней области типа.
В дереве Типы, на которые указывает ссылка отображаются ссылки, активные для выбранного в верхней области типа.
Чтобы отобразить экземпляры типа, выбранного в верхней области, нажмите кнопку "Просмотреть экземпляры" рядом с типом объекта.
На панели Экземпляры , которая открывается в верхней области, отображаются экземпляры выбранного объекта текущего снимка. На панелях Пути к корню и Объекты, на которые указывает ссылка отображаются объекты, которые ссылаются на выбранный экземпляр, а также типы, на которые ссылается выбранный экземпляр. Если создать снимок после остановки отладчика и навести указатель мыши на ячейку в столбце Значение, во всплывающей подсказке отобразятся значения объекта.
Отчеты о собственных типах
Щелкните текущую ссылку в ячейке Выделения (разн.) или Размер кучи (разн.) в сводной таблице "Использование памяти", отображаемой в окне Средства диагностики.
В окне Экземпляры отображаются все экземпляры выбранного типа. При выборе экземпляра на панели Стек вызовов выделений отображается стек вызовов, использованный для создания этого экземпляра.
В окне Экземпляры отображаются все экземпляры выбранного типа. При выборе экземпляра на панели Стек вызовов выделений отображается стек вызовов, использованный для создания этого экземпляра.
Чтобы отобразить стек вызовов для выбранного типа, в раскрывающемся меню Режим просмотра выберите пункт Представление стеков .
Чтобы отобразить стек выделений для выбранного типа, выберите Стеки.
Отчеты об изменениях
В окне Средства диагностики щелкните в необходимой ячейке сводной таблицы Использование памяти разницу в значениях.
Выберите моментальный снимок в списке Сравнить с , в котором отображаются управляемые или собственные отчеты.
С помощью отчета об изменениях в основной отчет можно добавить столбцы, помеченные надписью (Разн.) , в которых будет отображаться разница между двумя выбранными снимками. Отчет об изменениях собственных типов может выглядеть следующим образом.
Блоги и видео
Следующие шаги
В этом руководстве вы узнали, как собирать и анализировать данные об использовании памяти. Если вы уже ознакомились с общими сведениями о профилировщике, можно перейти к анализу данных об использовании ЦП в приложениях.
После запуска средства можно увидеть пути выполнения функций, для которых выделяются объекты. Затем можно проследить путь к корню дерева вызовов, который использует больше всего памяти.
Установка
Откройте профилировщик производительности (ALT+F2) в Visual Studio.
После его запуска просмотрите сценарий, который вы хотите профилировать в приложении. Затем выберите Остановить сбор или закройте приложение, чтобы просмотреть данные.
Щелкните вкладку Выделение. Теперь содержимое окна должно выглядеть как на снимке экрана ниже.
Теперь вы можете проанализировать выделение памяти объектам.
Во время сбора средство отслеживания может замедлить работу профилированного приложения. Если производительность средства отслеживания или приложения замедлена и если не требуется отслеживать каждый объект, можно настроить частоту выборки. Для этого на странице сводки профилировщика рядом со средством отслеживания щелкните значок шестеренки.
Настройте необходимую частоту выборки. Такое изменение улучшит производительность приложения во время сбора и анализа.
Дополнительные сведения о том, как сделать средство более эффективным, см. в статье Оптимизация параметров профилировщика.
Анализ данных
В предыдущем графическом представлении на верхнем графе показано количество активных объектов в приложении. На нижнем графе Object delta (Изменение объекта) показано процентное изменение объектов приложения. Красные столбцы обозначают, что была проведена сборка мусора.
Можно отфильтровать табличные данные, чтобы отображать действия только для указанного диапазона времени. Можно также увеличивать или уменьшать граф.
Выделение
В представлении Выделение показано местонахождение объектов, которым выделена память, и объем выделенной им памяти.
Столбец Тип содержит список классов и структур, занимающих память. Дважды щелкните тип, чтобы просмотреть его обратную трассировку в виде инвертированного дерева вызовов. Только в представлении Выделение можно просмотреть элементы в выбранной категории, занимающей память.
В столбце Выделения показано количество занимающих память объектов, относящихся к определенному типу выделения или функции. Этот столбец отображается только в представлениях Выделение, Дерево вызовов и Функции.
Столбцы Байты и Средний размер (байты) по умолчанию скрыты. Чтобы их отобразить, щелкните правой кнопкой мыши столбец Тип или Выделения, а затем выберите параметры Байты и Средний размер (байты) , чтобы добавить их в диаграмму.
Эти два столбца похожи на Всего (выделения) и Собственные (выделения) за тем исключением, что вместо количества объектов, занимающих память, в них показан общий объем занимаемой памяти. Эти столбцы отображаются только в представлении Выделение.
В столбце Имя модуля показан модуль, содержащий вызывающую функцию или процесс.
Все эти столбцы можно сортировать. Для столбцов Тип и Имя модуля можно сортировать элементы в алфавитном порядке по возрастанию или убыванию. Для столбцов Выделения, Байты и Средний размер (байт) можно сортировать элементы по увеличению или уменьшению числовых значений.
Символы
На вкладках Выделение, Дерево вызовов и Функции отображаются следующие символы:
— тип значения, например целое число.
— коллекция типа значения, например массив целых чисел.
— ссылочный тип, например строка.
— коллекция ссылочного типа, например массив строк.
Дерево вызовов
В представлении Дерево вызовов отображаются пути выполнения функций, содержащие объекты, для которых выделяется много памяти.
В столбце Имя функции показан процесс или имя функции, содержащей объекты, для которых выделяется память. Отображение зависит от уровня проверяемого узла.
В столбцах Всего (выделения) и Общий размер (байты) отображается количество выделенных объектов и объем памяти, используемые функцией и всеми другими функциями, которые она вызывает.
В столбцах Self (Allocations) (Собственные (выделения)) и Self-Size (Bytes) (Собственный размер (байт)) отображается количество выделенных объектов и объем памяти, используемый одной выбранной функцией или типом выделения.
В столбце Average Size (Bytes) (Средний размер (байт)) отображаются те же сведения, что и в представлении Выделения.
В столбце Имя модуля показан модуль, содержащий вызывающую функцию или процесс.
При нажатии кнопки Развернуть критический путь высвечивается путь выполнения функции, содержащий множество объектов, для которых выделяется память. Алгоритм высвечивает путь с наибольшим количеством выделений, начиная с выбранного узла, помогая изучать использование памяти.
Кнопка Показать критический путь отображает или скрывает значки пламени, указывающие, какие узлы входят в критический путь.
Функции
В представлении Функции показаны процессы, модули и функции, для которых выделяется память.
В столбце Имя отображаются процессы в качестве узлов верхнего уровня. Под процессами располагаются модули, а под ними — функции.
В этих столбцах приводятся те же сведения, что и в представлениях Выделение и Дерево вызовов:
- Total (Allocations) (Всего (выделения));
- Self (Allocations) (Собственные (выделения));
- Общий размер (байт) ;
- Self-Size (Bytes) (Собственный размер (байт));
- Average Size (Bytes) (Средний размер (байт)).
Collection
В представлении Коллекция показано, сколько объектов было собрано или осталось во время сборки мусора. В нем также имеются круговые диаграммы для визуализации собранных и сохранившихся объектов по типу.
- В столбце Собрано показано количество объектов, собранных сборщиком мусора.
- В столбце Осталось показано количество объектов, сохранившихся после работы сборщика мусора.
Средства фильтрации
В каждом из представлений Выделения, Дерево вызовов и Функции есть параметры Показать только мой код и Show Native Code (Показать машинный код), а также поле фильтра.
Перехватывать new и delete ? сомнительно, не очень верится, что все будет работать только через эти операторы.
Словом, никто не подскажет, как все-таки лучше, надежнее и точнее всего это делать, причем желательно не извне, а из самой программы?
Конкретнее - Windows, использую Visual C++ 2017.
Как посмотреть затрачиваемые ресурсы программы? сообщала о самых разнообразных ошибках - ошибки в студию
@user7860670 Уже завтра, сегодня голова уже не варит. Тот проект я уже прибил, заводиться с нуля сейчас не хочу.
Использую VS2015 pro, в отладчике есть отличная штука - Diagnostic Tools, которая позволяет снять снепшот памяти и проанализировать, чего и в каких количествах в ней выделялось. (Подозреваю, что VS2017 должна обладать этой тулзой тоже - в отладчике меню Debug->Windows->Show Diagnostic Tools)
1 ответ 1
Для получения информации о памяти процесса есть несколько API, наиболее интересны из них:
Показатели, которые я здесь использую:
Private committed memory (Частная выделенная память) - объем виртуальной памяти процесса в состоянии MEM_COMMIT, принадлежащей исключительно этому процессу. Состояние MEM_COMMIT значит, что под данную память выделено место в файле подкачки, а в физической памяти оно может быть либо выделено, либо нет. Из данного значения исключена память, которая является разделяемой между разными процессами - отображенные на память файлы и загруженные DLL, отсюда "private". Звучит сложно, но по сути это и есть главный показатель, сколько процесс "жрет" памяти.
Working set (Рабочий набор) - общий объем физической памяти, выделенной процессу, в том числе разделяемой между несколькими процессами.
Private working set (Частный рабочий набор) - объем физической памяти, принадлежащей исключительно данному процессу. Этот показатель более полезен, чем предыдущий, но получить его сложнее.
Heap size - объем выделенной динамической памяти (помимо непосредственно выделенного нами через new , включает также то, что выделено внутренне библиотеками).
Какой из этих показателей использовать, сильно зависит от ситуации. Если речь о спортивном программировании и ограничении количества используемой памяти на решение задачи, интересен Private committed memory. Если же речь идет об оценке нагрузки на систему, важнее показатели физической памяти, так как она более дефицитна, чем место в файле подкачки.
У меня есть две программы, одна на C ++, другая на ассемблере. Я хочу сравнить, сколько памяти они используют при работе соответственно. Как я могу это сделать?
Я провожу тестирование в Windows, но я также хотел бы знать, как это сделать в Linux.
Запускаем программу в одной оболочке. Откройте другую оболочку и выполните команду «top». он перечислит запущенные процессы и поместит много памяти, которую они потребляют. я думаю, вы можете опросить / proc / yourprocessid / stat, чтобы узнать, сколько памяти он использует с течением времени.
Диспетчер задач Windows может показать использование памяти каждым процессом. Думаю, вы могли бы использовать вместо этого Valgrind, но я не вижу в этом смысла. В Linux используйте Valgrind или ps.
В Windows вы можете использовать функцию GetProcessMemoryInfo .
Зависит от вашей операционной системы - вы ожидаете, что у вас будут инструменты, которые сообщат вам, сколько памяти потребляется при запуске приложений.
Было бы очень сложно получить ответ, изучив код, запустите приложения, используйте диагностику своей платформы.
В зависимости от размера программ это может быть практически невозможно.
Если они не очень большие, вы можете увидеть, сколько памяти они выделяют; например, int займет 4 байта, char - 1 байт и т. д. Сборка очень прозрачна в том, сколько памяти она использует, даже на машине x86. Cpp почти так же прозрачен, если вы точно отслеживаете создание объекта и уничтожение / выделение памяти.
В Windows для этого можно использовать Системный монитор Microsoft. Пуск, Беги, "перфмон". Этот инструмент будет сообщать всевозможные статистические данные о процессах и предоставлять вам графики. В общем, вам будет интересно рассказать о «Частном рабочем наборе». Это покажет вам, сколько памяти ваш процесс зарезервировал для собственного использования.
Если вы хотите просто использовать свою кучу, и вы хотите сделать это программно, вам следует изучить Отладочная куча CRT.
Я не уверен насчет Linux, извините.
В Windows я нашел очень полезным монитор адресного пространства, особенно для того, чтобы посмотреть, насколько фрагментирована ваша память. .
В Linux попробуйте valgrind . Это удивительный инструмент, в котором слишком много функций, чтобы простые смертные могли полностью понять. Взгляните на massif valgrind .
В Windows вы можете использовать Системный монитор.
Использование монитора производительности
Запустите Performance Monitor из меню «Пуск» / «Администрирование» / «Производительность».
Если вы хотите начать регистрацию:
Выберите журнал производительности и предупреждение> Текущий журнал в левой части браузера.
Выберите «Новые настройки журнала».
Дайте журналу подходящее имя, например performance_Server для сервера
Это предложит вам одно меню. На вкладках «Общие» нажмите кнопку «Добавить» и выберите процесс, который вы хотите отслеживать. (Измените объект производительности на процесс, для «выбрать счетчики из списка» выберите «личные байты», для «выбрать экземпляры из списка» выберите процесс, который вы хотите отслеживать.) После этого нажмите «Добавить и закрыть». Теперь измените интервал в соответствии с требованиями тестового примера. Теперь перейдите на вкладку «файлы журнала» и измените тип файла журнала на формат csv или tsv. Теперь примените и нажмите ОК.
Если вы хотите запустить / остановить ведение журнала:
Выберите конкретный журнал, который вы хотите запустить и остановить.
На панели инструментов выше вы увидите кнопки запуска и остановки.
Если вы хотите проверить содержимое файла журнала:
Щелкните Параметры / Данные из…
Выберите файл журнала для просмотра, нажмите ОК.
Перейти к экрану карты (Просмотр / Карта)
Нажмите Edit / Add to chart.
Добавьте необходимые элементы в диаграмму. (В случае, если требуется проверить утечку памяти, вам необходимо просмотреть PrivateBytes процессов и их _Total)
Считайте значения из диаграммы (минимальные и максимальные значения отображаются в нижней части диаграммы)
Если вы хотите отслеживать передачу данных по сети:
Отображение экрана карты (Просмотр / Карта)
Нажмите Edit / Add для входа в журнал и выберите элементы Network Interface \ Bytes Sent, если вы установили его в dl.
Или Network Inerface \ Bytes Received, если вы установите его в CRS-PC +
Мониторинг использования памяти:
В меню Пуск / Программы / Администрирование / запустите программу Performance Monitor.
Нажмите на кнопку, чтобы открыть окно добавления процессов.
Заполните поля следующим образом:
Счетчик: частные байты
Экземпляр: процесс, для которого необходимо отобразить занятость памяти.
Повторите последние два шага для каждого процесса, который необходимо отобразить в памяти.
Закройте окно, которое добавляет процессы
Внизу окна монитора производительности находится список ранее выбранных процессов.
- Теперь откройте файл Perfmon_.csv или Perfmon_.tsv с помощью WordPad или Excel.
Если вы открыли файл в Excel, то с помощью опции «Сохранить как» сохраните файл в формате Microsoft Excel.
Читайте также: