Мониторинг использования памяти в приложении Delphi - PullRequest
8 голосов
/ 27 мая 2011

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

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

Вот что я попробовал:

  1. ReportMemoryLeaksOnShutdown: = True в моем основном файле проекта, но ничего не возвращает.Поэтому он либо не отслеживает утечку памяти в пакетах, которые загружаются динамически, либо освобождает память до закрытия приложения.
  2. AQTime.Предполагается, что это очень вау продукт, но я нахожу его совершенно не в восторге.Если я использую профилировщик распределения, я получаю сотни строк, не содержащих ничего полезного.Просто адрес памяти, размер и что-то вроде «стандартного выделения VCL».Якобы это разбивает информацию по рутине, но я просто получаю плоский список без какой-либо рутинной информации.Поэтому я не думаю, что это работает.

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

Ответы [ 5 ]

11 голосов
/ 27 мая 2011

FastMM включает в себя простой графический интерфейс, который отображает использование памяти во время работы приложения.

Пример проекта находится в каталоге Demos/Usage Tracker.

3 голосов
/ 27 мая 2011

Я бы точно использовал AQTime и НИЧЕГО, чтобы определить информацию об использовании памяти.Вот пример информации об использовании памяти, которую я ожидал бы найти:

  1. Точная строка, которая выделяет память с помощью GetMem, TObject.Create.
  2. Хорошие счетчики количества объектов и общего количествапамять, используемая различными типами классов.

Прежде всего, давайте разберемся с очевидными вещами:

A.Вы должны следовать инструкциям AQTime и настроить параметры своего проекта, в том числе параметры компилятора и компоновщика, которые хорошо описаны в файлах справки.Особенно вам нужны символы Turbo Debugger (TD32) в настройках компоновщика и все остальные параметры настройки, которые вы настроили бы для любой другой отладочной сборки вашего проекта.

B.Прежде чем использовать его со своим собственным приложением, вы должны сначала попробовать учебник.

Короче говоря, я интенсивно использовал AQTime, и когда у меня возникли проблемы, они были решаемы, так что не давайтееще на AQTime.Если вы не можете заставить работать свое большое приложение, начните с изучения того, как протестировать небольшое приложение, демонстрацию или учебное упражнение.

Обновление: Я только что сам проверил его, и я обнаружил, что у меня возникают проблемы даже при создании базовой демонстрации AQTime 7 с профилировщиком Allocation, как описано.Я использую AQTime 7.10.380 pro.

1 голос
/ 27 мая 2011

Для отслеживания использования памяти приложения вы можете использовать некоторые из инструментов sysinternals (Process Explorer, VMMap, Rammap), чтобы посмотреть на них с точки зрения операционной системы, но такие инструменты, как AQTime, фактически скажут вам, ктоВыделенная память, когда и где, если вы сконфигурируете и используете ее должным образом - она ​​имеет начальную крутую кривую обучения, внимательно прочитайте документацию, это не инструмент «беги и читай результаты».Это может быть не утечка, чтобы взорвать приложение, это может быть просто загрузка и хранение в памяти слишком большого количества данных.Есть хорошие шансы, что вы загружаете огромный набор данных в память или что-то подобное, например, двунаправленный набор данных будет кэшировать предыдущие записи, чтобы обеспечить обратную навигацию, однонаправленный не будет и будет использовать гораздо меньше памяти.Некоторые библиотеки более эффективны, чем другие, при настройке памяти для полей varchar и т. П. (Некоторые могут всегда выделять размер поля varchar, другие могут быть умнее и просто выделять место для данного поля записи, хотя это делает управление изменениями записей болеесложно).Это может быть промежуточный результат, который хранится в памяти слишком долго, неправильный выбор структуры данных или слишком много рекурсии ... трудно сказать, не глядя на код.

0 голосов
/ 27 мая 2011

Скорее всего, проблема заключается в том, что вы удерживаете набор данных в памяти во время его циклического просмотра, и если у вас есть сотни тысяч (или миллионов) записей, это может превысить 1 ГБ.Кажется, я вспоминаю свойство набора данных UniDirectional, которое гарантирует, что память может быть освобождена во время работы, поскольку вы не можете вернуться к предыдущей записи в наборе данных (как обычно), если это свойство установлено.

Edit: Я думаю, что это было только для BDE, но dbExpress по умолчанию использует однонаправленные наборы данных, если я не ошибаюсь.

0 голосов
/ 27 мая 2011

Находятся некоторые инструменты здесь на About.com для утечек памяти Delphi: http://delphi.about.com/od/toppicks/tp/aatpmemleak.htm

...