We all know that recycling is good for the environment, but recycling virtual storage is great for applications that run under the z/OS Language Environment (LE). I am referring not only to reusing virtual storage, but also allocating storage wisely — for example, obtaining a large enough chunk before execution to avoid many trips back to the well while the application is running.
Obtaining or freeing virtual storage has a cost which can add up quickly, especially in a transaction-driven LE application under load. Reducing the number of obtains and frees can lower the CPU utilization of the application and improve elapsed time. You probably know that LE is widely used to support COBOL, C/C++, PL/I, and FORTRAN programs on the mainframe. But did you know that LE also provides tuning options to optimize virtual storage usage without changing application source code, or recompiling? This article will introduce you to some of LE’s powerful virtual storage tuning options.
When an LE application starts, LE obtains a chunk of virtual storage called a “heap” which it manages on behalf of the application. When the application requests dynamic storage through APIs such as malloc(), LE parcels out part of the heap for it. “Stack” storage, used for program call linkage and local variables, is also carved out of the heap. The heap scheme removes complexity from applications, and centralizes the virtual storage management to LE, which allows LE to minimize expensive virtual storage obtains and frees--with proper tuning.
RPTOPTS(ON): When activated, RPTOPTS generates a report of the LE runtime options that were in effect when an application was running. RPTOPTS is a useful tool for debugging or tuning, but should not be left on in production because it may increase the time it takes for an application to run.
RPTSTG(YES): RPTSTG is an option you can use to report on stack and heap usage. The report contains the initial and increment sizes you selected, and how many times you obtained and freed a segment of the stack and heap. These statistics are invaluable for calculating ideal initial and increment sizes. There is a significant performance impact, so do not use RPTSTG(YES) unless you are tuning the application.
Smart choices for HEAP and STACK initial and increment sizes: If the initial size is exceeded, then LE obtains an increment--an additional chunk--of virtual storage. When that increment is filled, LE obtains another increment, and so on. If this process repeats too often, it noticeably costs additional CPU time and slows down your application. LE has several types of heaps and stacks, with specific purposes. They have the same tuning parameter format, but different default values. The AMODE 24 heap has a default initial size of 8K and increment size of 4K, compared to the AMODE 31 heap initial and increment size default of 32K. The lower defaults make sense for avoiding 24-bit virtual storage constraints, but may leave opportunity for improvement on the table. ANYHEAP and BELOWHEAP are separate heaps used just for LE internal functions, but you can still report on them and tune them. For those planning to exploit or already exploiting 64-bit storage, LE also has a heap for AMODE 64 applications called HEAP64. You can run your application on a test system with RPTSTG(YES) to see stack and heap usage statistics which show what heaps and stacks your programs use, and how efficient your initial and increment size elections are.
For CICS-based applications, CICS TS has a function called automatic storage tuning, which attempts to remove some of this management complexity. Automatic storage tuning is beyond the scope of this article. CICS also automatically adds 16 bytes to heap size for its storage check area. In order to avoid crossing a 4K page boundary you should specify a size that is 16 bytes less (e.g., 4096 becomes 4080). Otherwise, LE automatically obtains the entire extra page, causing storage fragmentation and additional overhead.
KEEP (not FREE): With FREE, LE creates and destroys a heap each time an application runs. The KEEP option (default for global HEAP option) allows LE to reuse heaps from one instance to the next, providing significant potential savings in virtual storage obtains and frees. When LE reuses the heap frequently, it is also more likely that the storage will remain in the CPU cache, reducing memory latency. If you find FREE in a heavily used heap, KEEP would be worth testing.
HEAPPOOLs: In a multithreaded application, each thread shares the same heap which can lead to storage contention. The HEAPPOOLs option takes advantage of an improved algorithm for parceling out cells of heap storage to different tasks with virtually no contention for that storage, which can reduce CPU time for multithreaded applications (this support is for PL/I and C/C++ applications only). In order to exploit HEAPPOOLs you must go through a documented tuning process, so it is not “for free,” but could be worth your while. The process consists of performing a “tuning run” with canned HEAPPOOL parameters and after the run, LE tells you what the optimal parameters are.
STORAGE: STORAGE is an option that allows you to initialize the heap and stack storage to zeroes or a prescribed single-byte value. Having LE initialize storage ahead of giving the application control can have a significant performance impact. No initialization, which is the default, alleviates the impact but requires applications to clear their working storage themselves. Initializing to a value, such as STORAGE(,,00) or STORAGE(00), has the most overhead. If you can avoid this option, then do so.
When used correctly, these LE runtime options can make applications much more responsible virtual storage users, saving CPU and elapsed time. Before activating new runtime options, test them, as with any change. For instance, increased storage usage may mean job REGION sizes need to be increased, and in the AMODE 24 example, testing ensures that your application does not exhaust virtual storage below the line. Check out the links under additional references for more details on the options discussed in this article, other tuning options, and lots more information on the z/OS Language Environment. Reduce, reuse, recycle, and reap the rewards.