|Memory is a critical resource, but some developers still underestimate its value. The cost of memory dominates the price of today's servers — in general, approximately 80% of hardware costs are attributed to memory. Yet even when developers work to use memory efficiently, the problem of undetected memory leaks often remains. Memory leaks occur during long-lasting stateful sessions (when a series of business objects is processed consecutively); memory is occupied, but not freed, once it is no longer needed. This all-too- common problem results in high memory consumption, tying up memory so that other users or programs can't use it. In my previous Performance & Data Management Corner column, I described a few options for solving memory leaks on software architecture and programming levels. Now I'd like to familiarize you with a tool that will allow you to analyze those memory leaks — and ultimately eliminate them. This tool is the ABAP Memory Inspector. Before we dive into ABAP Memory Inspector's functionality and how to use it, let's investigate some familiar SAP tools that developers can employ to find and identify user sessions with high memory usage, the main hiding places for memory leaks.
In this article, we'll focus on the ABAP Memory Inspector functionality available in SAP NetWeaver 7.0. ABAP Memory Inspector is also available in SAP NetWeaver 6.20 support package 29, SAP NetWeaver 6.40, SAP NetWeaver 7.0, and later releases.
Identify Potential Memory Problems
For developers, the first step to finding and stopping memory leaks is to take advantage of some of the transactions that SAP NetWeaver offers:
- SM04 (User session memory list): To look for memory leaks, you need to monitor memory consumption while several consecutive business objects are processed within the same user session. Transaction SM04 shows the current memory usage of a user session. SM04 is ideal for online, real-time monitoring. For example, you can easily monitor online the memory growth of a long- running dialog transaction or batch job (see sidebar for more information about using SM04).
- STAD (SAP Workload: Business Transaction Analysis): STAD is ideal for monitoring the resource consumption of a transaction after processing has completed. To find the maximum level of memory consumption of a dialog transaction or a batch job after it has finished, check the statistical records — which are recorded by default — in the SAP Workload Monitor using the STAD transaction. Once you enter filter criteria (your user name, for instance), you'll see a list of the dialog steps you processed. This list contains a "Memory Used (kB)" column, which shows the value of the memory consumed at the point in time when the dialog step finished processing.
|Transaction SM04 is ideal for online, real-time monitoring, while STAD is ideal for monitoring the resource consumption of a transaction after it has finished processing.
Use the ABAP Memory Inspector to Analyze the Problem
Once you have used these tools to pinpoint the source of your memory problem, you can further analyze the problem with ABAP Memory Inspector by taking snapshots of the memory usage of a user session. To find memory leaks in the ABAP virtual machine (VM), take two memory snapshots at different times — for example, one after the nth purchase order has been processed and another after the (n+1)th purchase order has been processed in one session. ABAP Memory Inspector will then allow developers to analyze facets of these snapshots, calculating the difference in memory allocation between them and displaying only those memory objects that are new or have changed in size. This way, you'll be able to pare down the number of memory objects that you'll need to analyze further. ABAP Memory Inspector also only lists dynamic memory objects — in-memory structures that are created or expanded in size during run time. Only those types of memory objects can cause memory leaks. They include the following:
- Bodies of internal tables (as created by statements like DATA itab TYPE TABLE OF )
- Strings (as created by statements like DATA lstring TYPE STRING)
- ABAP objects or class objects (such as a class created by the CREATE OBJECT statement)
- Anonymous data objects (such as a data type created by the CREATE DATA statement)
Methods of Taking Memory Snapshots
There are several ways to trigger a memory snapshot. For SAP GUI transactions, the easiest way is to use the System menu available in all SAP GUI-based screens through the path System ? Utilities ? Memory Analysis ? Create Memory Snapshot. To take a memory snapshot of a non-SAP GUI application or to take the snapshot when the maximum memory consumption is reached (during the processing of a screen, for example), you will have to use the ABAP Debugger.
- With the Classic ABAP Debugger, create a snapshot through the menu path Development ? Memory Analysis ? Create Memory Snapshot.
- In the New ABAP Debugger, the memory analysis functionality is not part of the default desktop and must be explicitly loaded into one of the user- specific desktops via the Replace Tool functionality (selecting Special Tools ? Memory Analysis in the list of available tools). Once this is done, you can take the snapshot as shown in Figure 1 by calling the Create Memory Snapshot service of the tool.
When working in the New ABAP Debugger window, do not use the menu path System ? Utilities ? Memory Analysis ? Create Memory Snapshot. Memory snapshots created this way only contain memory objects of the ABAP Debugger session rather than the user session you are trying to analyze.
It is also possible to trigger memory snapshots from within ABAP code by calling the WRITE_MEMORY_CONSUMPTION_FILE method of class CL_ABAP_MEMORY_UTILITIES. This enables developers to deal with complex trigger conditions that would make it very difficult to trigger the memory snapshot manually at the right time. Note that this method requires you to manually change the ABAP code and should only be used in development systems. Also, due to high CPU overhead and disk space consumption, this method can't be used in the production system.
Taking a memory snapshot in the New ABAP Debugger
Methods of Analyzing Memory Snapshots
The simplest way to analyze memory snapshots — no matter how you created them — is to call the ABAP Memory Inspector with transaction S_MEMORY_INSPECTOR via the command field or to use the menu path System ? Utilities ? Memory Analysis ? Compare Memory Snapshots. However, if you start the ABAP Memory Inspector directly from the Classic ABAP Debugger (via Development ? Memory Analysis ? Compare Memory Snapshots), you will gain a special advantage: The ABAP Memory Inspector session and the ABAP Debugger session are linked, making it possible to display the content or the value of the memory object found in the ABAP Memory Inspector directly in the ABAP Debugger. To do this, right click on the object in the ABAP Memory Inspector session and select Display in Debugger, then switch to the ABAP Debugger screen and press ENTER. With the download and upload functionality of ABAP Memory Inspector, you can also analyze snapshots in any other system that is running on the same SAP NetWeaver release as the system under test.
Further Investigating Memory Snapshots
ABAP Memory Inspector enables you to select up to two memory snapshots — snapshot t_0 and snapshot t_1. You can then choose to analyze the memory usage in each snapshot individually by selecting (t_0) or (t_1) in the dropdown list in Figure 2, or the memory change between the two (t_1 – t_0). The system automatically selects the snapshot with the later timestamp as snapshot t_1. This means that each positive value in the comparison t_1 – t_0 indicates an increase in memory consumption.
Selecting a single snapshot or a snapshot comparison for analysis in ABAP Memory Inspector
For each snapshot or comparison of two snapshots, you can display different views, such as the Overview and Ranked List by Type views, by clicking on the View dropdown list. Let's break down the values displayed in Figure 2:
- MM_TOTAL shows the total size of one internal session at the time the snapshot was taken. Compare this with the values retrieved by SM04 or STAD to verify if you are using the correct internal session.
- ABAP_TOTAL displays the amount of memory that can be directly assigned to a single memory object like an internal table. The difference between MM_TOTAL and ABAP_TOTAL indicates the administrative part of the ABAP runtime system or shows that some runtime structures, like directories for memory objects, cannot be assigned to a single ABAP memory object. But reducing the total number of ABAP memory objects will reduce the quantity of the ABAP_TOTAL and the MM_TOTAL values, since the corresponding memory required for administrative data is also reduced.
- Delta MM_Total (GC) shows the amount of memory that is freed during the ABAP Memory Inspector's automatic garbage collection (GC). The Memory Inspector triggers this GC before a snapshot is taken to avoid including dead objects in the snapshot. If this value makes up a significant part of the overall user session (MM_TOTAL), investigate which classes these ABAP objects belong to and try to uncover why they produce such a large amount of garbage. You can then take steps to optimize these programs — by reusing objects, for example.
When analyzing memory snapshots, it is important to distinguish between allocated and used memory, and among bound memory, referenced memory, and the object size.
Allocated and Used Memory
The ABAP runtime does not allocate the memory line by line for each new line of an internal table, nor does it allocate the memory character by character for strings when new characters or words are added (see Figure). For example, for internal tables, the system completes a pre-allocation in such a way that a new memory page is reserved for several lines (denoted by m in the Figure) of the itab1 table. The size m is automatically optimized by the ABAP runtime – for example, a rapidly growing table may cause the next page to be twice the size of the previous page. Generally though, the developer does not need to take care about the details of the memory allocation – with one exception (see sidebar).
Developers should keep in mind the difference between the allocated memory (the brown and yellow area together, in Figure 3 below) and the used memory (brown area). The values of used and allocated memory should be similar. If this is not the case, developers should redefine the size of the first table page using the INITIAL SIZE parameter. They should also explore options for deallocating memory, such as:
- CLEAR or REFRESH: These commands deallocate the memory of all indices -- that is, the primary index, as well as secondary indices on internal tables (these secondary indices are only available in SAP NetWeaver releases 7.10 and up), but keeps the first page allocated to the body of the internal table. Use these commands if the internal table will be reused again during the lifecycle of the session.
- The FREE statement not only deallocates the memory for all indices, it also deallocates the whole body of the internal table. Use this statement if the internal table will not be reused during the lifecycle of the session.
- The DELETE statement does NOT free any memory space, even empty pages are kept. In some cases it might be useful to optimize the storage of a table which was shrunk by the DELETE statement. If an initially huge internal table with many lines is reduced to a small table with only a few entries by using DELETE and if the resulting small table will be kept for a long time (during the rest of an endless transaction or in a batch job, for example), then it might be worthwhile to free the empty pages.
Note that memory allocation for strings cannot be influenced by developers at all.
Illustration of memory quantities as explained in the text
Object Size, Bound Size, and Referenced Size
Besides the distinction between used and allocated memory, which we described earlier, there is another way of categorizing memory usage when analyzing memory snapshots: through object size, referenced size, and bound size. In the above table, "Object size" refers –to the size of the memory object itself. The benefit of determining this object size is the fact that it can be summed up to calculate the overall object size of a set of memory objects -- to find out memory usage per software package, for example.
While this quantity is important, it can be more helpful to find out how much memory is bound by a memory object and in turn, how much memory will be freed if the corresponding memory object is deleted. If a memory object or the reference to a memory object can be deleted, the quantity given by "Bound size" will be freed (either immediately or after the next GC run).
The "Referenced size" refers to the sum of the object sizes of all memory objects, which can be reached by following all references from the leading memory object to all its related memory objects.
Compare Memory Snapshots
After developers have collected enough information about memory allocations and relevant memory values, they can interpret and analyze the snapshots by comparing them in ABAP Memory Inspector. There are some important aspects to keep in mind when taking snapshots:
Remember that if you start ABAP Memory Inspector directly from the Classic ABAP Debugger, you can display the content of memory objects directly within the Debugger. Load the two relevant memory snapshots and switch to the Ranked List by Type view. In this view, memory objects of the same type — such as all ABAP objects that belong to the same class — are grouped together by default, resulting in a manageable list with fewer entries to be analyzed. However, you can expand the list by manually drilling down into individual ABAP objects. Once you reach the screen shown in Figure 4 , there are two approaches you can take to compare your memory snapshots.
- Take both snapshots at defined, identical points in your business process — for example, one before and one after a business object was processed (when processing open purchase orders from a work list, for instance).
- Do not take snapshots for the first business object or work package being processed. Instead, you should start at a time when all programs have already been loaded.
- Make sure exactly the same business process is executed for each snapshot and that no additional functionality is run. Otherwise it will be hard to distinguish whether a new memory object in the snapshot is due to a memory leak or the result of additional business functionality. For example, do not take the first snapshot for a purchase order with standard trading goods and the second snapshot for a purchase order with configurable materials.
The memory snapshot is color coded to make it easy for developers to analyze
Bound size is the quantity of memory that will be freed — immediately or after a garbage collection (GC) run — by deleting a particular memory object or all references to it.
Referenced size is the sum of the size of all memory objects that can be reached by following all references from a memory object to all related memory objects.
Approach #1 — Identify the Largest Individual Objects Contributing to a Memory Leak
To find the largest individual contributors to a memory leak, sort the ranked list in the memory snapshot according to the values in the Bound (Allocated) column in descending order (see the Key Terms box on the previous page to learn more about what these column titles mean). This divides the table into three categories: red, black, and blue (refer again to Figure 3).
- The top of the red list shows the largest new memory objects. Developers should examine each object closely to figure out if it is needed or if it can be deleted. By expanding the memory object in the ABAP Memory Inspector, the full information about all references to the memory object is displayed. More than one reference often exists, especially for ABAP objects, because developers sometimes forget to clear unneeded references, thus keeping the memory object alive. If developers need to follow the hierarchy of these references upward beyond the single level shown in the memory snapshot to locate the root cause of a memory leak, they must use the ABAP Debugger.
- The top of the black list shows the memory objects with the largest growth. Developers should view the content of each of these memory objects in ABAP Debugger to see if, for example, data belonging to the previously processed business object is being kept unnecessarily.
- The blue list contains the objects that were no longer alive when the t_1 snapshot was taken — indicating that they were no longer taking up memory. Here, developers should look for corresponding entries for these memory objects in the red list because that would indicate that one instance of the memory object was deleted and a new, identical instance (with a new ID) was created. If the size of both memory objects is identical at times t_0 and t_1, then these objects are not causing a memory leak. Nevertheless, in order to save CPU time, developers should consider reusing the memory object instead of deleting and re-creating it.
Approach #2 — Identify the Largest Object Cycles Contributing to a Memory Leak
An alternative, top-down approach is to look at your memory snapshot with a focus on finding the largest object cycles. To do so, sort the list in descending order according to the Referenced (Allocated) column. The aim of this approach is to find larger networks of memory objects that are kept alive, but may no longer be needed. Often, in some leading object, the decisive reference is kept alive needlessly. By releasing this reference, a whole network of objects can be deleted at once. This is the advantage of a top-down analysis of the largest object cycles. On the other hand, not every memory object that is inspected may be a good candidate to throw away since that object may still be alive on purpose.
Outlook and Conclusion
Memory is a valuable resource and should be treated as such. Since memory leaks do not easily show up in single user tests — which are often done during development — it's up to developers to proactively look for memory leaks and ensure that they aren't slowly draining away a crucial resource. SAP offers a variety of tools — from basic transactions, such as SM04 and STAD, to the ABAP Memory Inspector — to not only detect memory leaks, but to analyze them and eliminate their sources as well. SAP is continuing to provide developers with enhanced functionality for memory conservation. With SAP NetWeaver 7.10, for example, developers will be able to take memory snapshots on ABAP Shared Objects areas, like application-managed buffers, which are becoming more and more popular — and therefore are a potential source of memory leaks. With existing tools and continued SAP support, developers can rest assured that they are well armed to battle memory problems now and in the future.
- "Analyze Memory-Related Problems in Your ABAP Programs in Less Time and with Less Effort Using the ABAP Memory Inspector" by Christian Stork and Wolf Hagen Thümmel (SAP Professional Journal, November/December 2004, www.SAPpro.com)
- "What You Don't Know About Memory Can Hurt You: A (Re)introduction to Efficient Memory Computing for Programmers and Developers," a Performance & Data Management Corner column by Winfried Schleier (SAP Insider, October-December 2007, www.SAPinsideronline.com)
- SAP Performance Optimization Guide (5th edition) by Thomas Scheider (SAP PRESS, http://store.sapinsider.wispubs.com)
Winfried Schleier (email@example.com) studied physics at the Friedrich-Alexander University of Erlangen-Nuremberg, Germany, and received his Ph.D. in computational physics. Winfried joined SAP AG in 1994 and has been a member of the Performance, Data Management, and Scalability team since its inception. His areas of responsibility are performance, benchmarking, and sizing of different SAP solutions. Currently Winfried is concentrating on methodologies and tools for memory optimization in the