In this section:
Overview
Inuse reports provide help you understand different aspects of your application.
- If you want to see how much memory is being used, try the usage summary and heap history reports.
- If you want to optimize your memory allocation strategy, perhaps by building your own allocator for blocks of certain sizes, the block frequency graph is appropriate.
- If you want to study the heap fragmentation caused by your algorithm, and understand the way that memory blocks are laid out, you should use the heap layout graph.
- If you want to see correlations between block id, block size, and stack traces in your program, use the query option. The following sections contain detailed descriptions of each Inuse report option.
Heap History Report
Clicking the History button or selecting Heap History from the Reports menu opens the Heap History window. If your program is running when you open this report, you will be able to monitor the amount of memory allocated by the program as it executes. If the program has ended its run, you can see how much memory was allocated across the history of the run.
The black area indicates the total size of the heap. The red, yellow, and blue areas constitute the make-up of the heap. The red area represents the amount of memory allocated by the program. The yellow area represents the amount of “overhead” associated with the memory that cannot be used by the application. The blue area represents the amount of leaked memory.
To change the sampling rate, that is, how much time passes before the graph is updated, click Sample or choose Sampling from the Options menu.
Block Frequency Report
The block frequency report shows the sizes of blocks typically being allocated by your program. If you are allocating many small blocks, you may want to switch to a memory allocation scheme that groups many small allocations into several larger ones. The block frequency graph groups together blocks that are similarly sized. Each bin (column) in the graph represents the number of blocks in a particular size range. Clicking a bin will show you the number and size range of blocks contained in that bin.
The right-most bin includes all blocks above a certain size. Click on the bin if it is very high to see the size range it covers. If the range is fairly wide, you can rescale the graph to include more bins by clicking Bins or choosing Bins from the Options menu. Entering a number higher than the number currently shown narrows the size range for each bin. Similarly, entering a number that is lower than the number currently shown should increase the size range included in each bin.
If all block sizes are currently represented on the graph, increasing the bin number will have no effect. You can alternate between a linear or logarithmic scale by clicking the Xscale and Yscale buttons. The Xscale button toggles the x-axis between linear and logarithmic scales. The Yscale button toggles the y-axis between linear and logarithmic scales. Choosing Horiz.log/log or Vert.log/log from the Options menu also toggles the x- or y-axis.
Heap Layout Report
The heap layout report shows the status of blocks in the program’s heap. Blocks are either free, allocated, overhead, or leaked. Click a block to see its address, size, and status. This information is shown in the lower right corner of the display screen.
If the block is allocated or leaked, a Memory Information window will also appear. The memory information window contains the block ID, address, stack depth, and stack trace. You can scan through different areas of the heap layout by clicking the Left and Right buttons or the F.left and F.right buttons, which quickly scroll the report, in the report toolbar. You can also change the scale by clicking Zoom in and Zoom out, which are also available in the Controls menu.
Time Layout Report
The time layout report shows how memory blocks are allocated across the run of the program. As each block is allocated, it is added to the end of the display. As blocks are freed, they are marked green.
From this display, you can watch how memory is allocated over the run of your program. As you see the patterns in which memory blocks are allocated and freed over time, you can better optimize your program’s use of memory. Memory leaks are also shown on this display.
You can scan through the run by clicking the Left and Right buttons or the F.left and F.right buttons, which quickly scroll the report, in the report toolbar. You can also change the scale by clicking Zoom in and Zoom out, which are also available in the Controls menu.
Usage Summary Report
The usage summary report shows how much memory you are using and how often calls have been made to each category of memory allocation functions malloc
, realloc
, and free
.
The malloc
category includes all functions that allocate dynamic memory, such as calloc
, memalign
, and XtMalloc
. The realloc
category, furthermore, includes all functions that relocate or resize dynamic memory blocks. The free
category includes all functions that free dynamic memory. You can calculate the number of blocks currently allocated by subtracting the number of free
functions from the number of malloc
functions.
The number reported in the Alloc field is the total number of bytes allocated dynamically by your program. The number reported in the Heap field is the total number of bytes currently allocated by the system to your program’s heap. The number reported in the Number of calls and Memory in bytes fields are the extreme value on the xaxis for each graph. The limit of each graph will change as Inuse updates the display with more memory allocation function calls.
Query Reports
Query is a powerful tool that makes it easier for you to understand how memory is being used by your program. With Query, you can find out:
- exactly how much memory is being allocated to blocks of a particular size or location
- how much memory is being allocated from a particular path
- the stack traces of blocks of a particular size or location
Queries represent a model of your program’s memory use that you can view from different perspectives that provides new insights in each successive report. As you come to understand how and where your program uses memory, you will be able to better optimize your program’s memory use. For example, if the Block Frequency report shows that your program is using many small allocations (creating a lot of memory overhead), you might want to know exactly how much memory is being allocated to these small blocks. You will also want to know which part of the code is responsible for creating them.
To find out how your program is distributing memory across block sizes, you can run a query that shows how much memory is being allocated to each size block. If you find that your small blocks contain a lot of memory, you can then run a query that gives you the block ids and stack traces responsible for creating these small blocks. Armed with this information, you will be able to make simple adjustments to your code that will result in a more effective use of memory. You can run queries on any combination of block id, block size, and stack trace. These queries can be as flexible or as restrictive as you choose, as you set the parameters. For more information, see Editing a Query. Running queries does not affect your program or its operation. By running different queries and trying different approaches, you will soon see how valuable and informative these reports can be.
Running a Query
Click the Query button in the Inuse toolbar to open the query manager. You can perform the following actions:
- Click Delete to delete the current query.
- Click New to start a new query.
- Click Load to open a saved query.
- Click Save to save the current query for later use.
- Click Edit to edit the currently selected query.
- Click Eval to evaluate the current query.
When you open a query, its name will appear in the Query Manager window. If you clicked New, the query will be named NoName
.
Editing a Query
Click Edit in the query manager screen to edit the currently selected query. You can perform the following actions:
- Change the name of a query.
- Set the lower and upper ranges for the block IDs you want to isolate.
- Set the lower and upper ranges for the block sizes you want to isolate.
- Enter an expression to isolate certain stack traces.
- Choose whether to receive a complete report, including block ID, block size, and stack trace data, or a summary of block size and/or stack trace information.
The default values for a query are 0
for the lower and upper block ID and block size ranges and no expressions in the stack trace area. This will produce the widest query, listing all memory blocks allocated by your program. You can filter a query to isolate particular block IDs, block sizes, and/or stack traces by specifying values you want to filter for and enabling the Filter by option. The Sum by option provides a useful summary of block size and stack trace data. Use it in combination with the Filter by option or on its own to get a breakdown of blocks by size and/or stack trace.
Example Query
Assume you want to learn more about blocks that are between 60 and 70 bytes in size. In the Block Size area, enter 60 in the lower range and 70 in the upper range. Enable the Filter by option and click OK. Running this query will return block IDs and stack traces for all blocks allocated by your program that are sized between 60 and 70 bytes.
Enabling the Sum by option for block sizes will return a list showing how much memory (in bytes) is being allocated to each block size in that range. You can enter filters for any or all three areas in a single query. This can help you find out the exact stack trace(s) responsible for the largest block allocations by your program, or conversely, to find out the size and location of memory allocated from a particular stack trace path. Edit your query and click OK.
To run the query, click the Eval button or choose Evaluate Query from the Commands menu. Query results will appear in a text window, as shown below: