Monitor memory usage in Delphi application

I inherited a very large subsystem from the programmer who left the company, and the first order of the business was to stop the process from running out of memory.

Basically, this is a cycle through a data set, within which we create and destroy a data module that turns off and does a lot of work. While this data module is created, you can see how the memory in the task manager is used all the time until it explodes. I seem to recall from an article I read many years ago that one cannot completely trust what the task manager reports, since the values โ€‹โ€‹are estimates, not real-time. Therefore, I am looking for alternatives.

Here is what I tried:

  • ReportMemoryLeaksOnShutdown: = True in my main project file, but it returns nothing. Thus, either it does not control a memory leak in packets loaded dynamically, or memory is freed before the application is closed.
  • AQTime. This is supposed to be a very strong wow product, but I find it completely genuine. If I use a distribution profiler, I get hundreds of rows that do not contain anything useful. Just a memory address, size and something in accordance with the "standard distribution of VCL". This supposedly breaks the routine information, but I just get a flat list without the usual information. So I donโ€™t think it works.

Is there any other tool that can help me track where this memory is allocated and not freed? I commented on small pieces of functionality all over the place to see where the problem goes away, and checked that everything that is explicitly highlighted is freed, but I still have a leak, and this can be a rather unpleasant process.

+7
source share
5 answers

I would absolutely use AQTime and NOTHING ELSE to determine memory usage information. Here is an example of memory usage information that I would expect:

  • The exact line that allocates memory using GetMem, TObject.Create.
  • Good object counters and shared memory used by various types of classes.

First of all, let me get the obvious things:

but. You must follow the AQTime instructions and set your project settings, including your compiler and linker settings, as is well documented in the help files. You especially need the Turbo Debugger (TD32) symbols in the linker settings, as well as all other parameters that you would configure for any other debug build of your project.

B. You must try the tutorial first before using it with your own application.

In short, I used AQTime heavily, and when I had problems, they were available to solve, so don't give up on AQTime. If you can't get your large application to work, start by learning how to test a small application, demo, or tutorial.

Update: I just tested it myself, and I found that I am having problems even with the AQTime 7 demo base with Allocation profiling work as described. I am using AQTime 7.10.380 pro.

+3
source

FastMM includes a simple graphical interface that displays memory usage while the application is running.

An example project is located in the Demos/Usage Tracker directory.

+11
source

To track application memory usage, you can use some of the sysinternals tools (process handler, VMMap, Rammap) to look at it from an operating system perspective, but tools like AQTime will actually tell you who allocated the memory, when and where , as long as you have configured and used it correctly, it has an initial steep learning curve, carefully read the documentation, this is not a tool to โ€œrun and read the resultsโ€. It may not be a leak to blow up the application, it may just be loading and storing too much data in memory. There is a good chance that you are loading a huge array of data into memory or something similar, for example, a bidirectional data set will cache previous records to provide reverse navigation, and unidirectional will not and will use much less memory. Some libraries are more efficient than others when setting up memory for varchar fields, etc. (some may always allocate the size of a varchar field, others may be smarter and just allocate space for a given record field, although this makes managing change records more difficult). This may be an intermediate result stored in memory for too long, an incorrect choice of data structure or too much recursion ... it is difficult to say without looking at the code.

+1
source

Some tools are found here on About.com for Delphi leaks: http://delphi.about.com/od/toppicks/tp/aatpmemleak.htm

0
source

The problem, most likely, is that you keep the data set in memory while passing through it, and if you have hundreds of thousands (or millions) of records, this can exceed 1 GB. I seem to remember the dataset UniDirectional property, which ensures that memory can be released when you go, because you cannot go back to the previous record in the data set (as usual) if this property is set.

Edit: I think this was only for BDE, but dbExpress uses Unidirectional datasets by default if I am not mistaken.

0
source

All Articles