The heart of the AS/400's work management system is in its storage pools. Sleek and elegant, they provide the memory management underpinnings for the AS/400's multitasking environment. Many people see storage pool management as an art, something to be mastered as a Shakespearean actor masters a role. Far from that lofty ideal, however, storage pool management consists of a set of easily understood concepts that even the Bard of Avon would appreciate for their simplicity and grace.
This article will introduce you to the concepts of storage pool management in OS/400. I'll discuss storage pools and activity levels and how they relate to the AS/400's work management scheme through subsystems. I'll give you all the basics you need to create your own OS/400 management scheme.
Neither a Borrower Nor a Lender Be
The main task of storage pools is to segment OS/400's working memory so that each subsystem can access its own specified piece of memory. By doing this, you can reduce resource contention among different subsystems. Storage pools allow you to provide dedicated resources to groups of jobs and to keep the resources separate. Storage pools allow you to better control the job flow on your AS/400 so that more work can get done.
To view your current storage pool setup, type in the Work with Shared Pools (WRKSHRPOOL) command. This command will bring up the display shown in 1.
To view your current storage pool setup, type in the Work with Shared Pools (WRKSHRPOOL) command. This command will bring up the display shown in Figure 1.
Your system's main memory can be divided into fourteen shared storage pools. Unlike private storage pools, these shared pools are assigned to different subsystems whenever you create or change a subsystem description. Each pool can be shared among many subsystems or dedicated solely to a particular subsystem for a special purpose. For example, you can assign a pool to handle nothing but SNADS processing in the QSNADS subsystem, or you can assign different batch subsystems, like QBATCH or QPGMR, to their own storage pools.
Four of these pools are predefined for subsystem use by OS/400. The *MACHINE pool is used for all operating system functions. The *BASE pool is generally used for batch and communications jobs. The *INTERACT pool is usually assigned to interactive processing and the *SPOOL pool is automatically assigned for printer spooling. The ten other shared pools, called *SHRPOOL1 through *SHRPOOL10, can be configured and assigned to different subsystems as needed.
Measure for Measure
Associated with each storage pool is an activity level. Storage pool activity levels specify the total number of jobs that can use memory from a storage pool at one time. When more jobs try to access storage pool memory than are allowed by the activity level, the excess jobs are temporarily swapped out of memory until another job relinquishes control of an activity level slot.
Storage pool activity levels are part of a larger AS/400 work management scheme. This scheme allows you to ensure that the throughput on your machine is consistent with your specifications. In addition to activity levels, work can be managed by the total number of active AS/400 jobs, maximum number of active jobs in each subsystem, maximum number of jobs originating from each job queue, and other system, subsystem, and job values.
Many different parameters control work flow on the AS/400, more than we can cover here. For the purposes of this article, it is sufficient to remember that storage pool activity levels are part of the overall work management scheme that ensures efficient processing. For a more complete description of how subsystems work, see "Solving the Mystery of Subsystems," MC, October 1994.
I Do Perceive Here a Divided Duty
Storage pool management consists of dividing memory into different storage pools and assigning storage pools to individual subsystems. Let's look at an example to see how this works.
The default storage pool for the QBATCH and QPGMR subsystems is the *BASE storage pool. In many environments, the operations staff uses QBATCH for such diverse tasks as product costing, invoicing, and printing pick lists while the programming staff uses QPGMR for compiles, conversions, and tests. A long- running memory intensive job, such as a Bill of Material regeneration, may slow down all other batch jobs. Similarly, if a programmer is running a twelve hour database conversion program that uses a lot of memory, daily production may suffer.
The solution is to create an additional storage pool with its own activity levels to service the programmers running in QPGMR. By doing this, production is separated from testing. The jobs will no longer compete with each other for memory, and batch processing will benefit from the split.
To Thine Own Self Be True
To implement our scheme, we need to create a separate storage pool for QPGMR. We must reallocate OS/400's main memory to divide it among the storage pools we want to use. As I mentioned before, there are ten storage pools available that can be assigned to any subsystem. These can be viewed and manipulated by entering the WRKSHRPOOL command. Suppose we want to assign *SHRPOOL1 to QPGMR. First, we have to move memory into that pool for it to use.
Let's say we want to give *SHRPOOL1 800K of memory and assign it an activity level of 1. This means that any job running in that pool will have a maximum of 800K to work with, but only one job can be active at a time.
Memory is always given to or taken away from the *BASE pool. All unallocated memory is automatically stored there and allocated memory is taken from there. To move memory into *SHRPOOL1, move your cursor down to *SHRPOOL1 on the Work with Shared Pools screen and type in 800 under Defined Size and 1 under Max Active. Press the Enter key and you'll find the display shown in 2.
Memory is always given to or taken away from the *BASE pool. All unallocated memory is automatically stored there and allocated memory is taken from there. To move memory into *SHRPOOL1, move your cursor down to *SHRPOOL1 on the Work with Shared Pools screen and type in 800 under Defined Size and 1 under Max Active. Press the Enter key and you'll find the display shown in Figure 2.
Notice that changing the memory size of the shared storage pools automatically reduces or increases the memory size of the *BASE storage pool. Increasing *SHRPOOL1 by 800K automatically decreases the *BASE pool by 800K. Conversely, if we change the memory size in *SHRPOOL1 back to 0, the memory size in the *BASE pool will automatically increase by 800K.
Therefore, when changing the memory size of the pools for a change in processing load, you give memory back to the *BASE pool before you give it to another pool.
What's in a Name!
Having memory in *SHRPOOL1 doesn't mean we can use it in QPGMR. We must first change the name of the default storage pool QPGMR uses from *BASE to *SHRPOOL1. Before we change any subsystem parameters, we end the subsystem to ensure that our changes take effect. We end the subsystem by typing in this command.
ENDSBS SBS(QPGMR) OPTION(*IMMED)
Once the subsystem is ended, we need to retrieve the storage pool operating parameters for QPGMR. To view these parameters, use the Display Subsystem Description (DSPSBSD) command as shown here.
DSPSBSD SBSD(QPGMR)
This command gives us all the parameters associated with subsystem QPGMR, as shown in 3. Type in option 2, Pool definitions, to display the storage pools assigned to the subsystem as shown in 4.
This command gives us all the parameters associated with subsystem QPGMR, as shown in Figure 3. Type in option 2, Pool definitions, to display the storage pools assigned to the subsystem as shown in Figure 4.
This screen shows us that the first Pool ID in QPGMR is assigned to the *BASE storage pool. Any job running in QPGMR that requests memory from Pool ID number 1 will get that memory from *BASE. To take the memory from *SHRPOOL1, use the Change Subsystem Description command (CHGSBSD) to change the storage pool location, as shown here.
CHGSBSD SBSD(QPGMR) + POOLS((1 *SHRPOOL1))
You can use DSPSBSD to view the change. This screen shows that the first subsystem storage pool is now *SHRPOOL1, as shown in 5. Restart the subsystem by using the Start Subsystem (STRSBS) command and QPGMR will take its memory from *SHRPOOL1 instead of *BASE.
You can use DSPSBSD to view the change. This screen shows that the first subsystem storage pool is now *SHRPOOL1, as shown in Figure 5. Restart the subsystem by using the Start Subsystem (STRSBS) command and QPGMR will take its memory from *SHRPOOL1 instead of *BASE.
This technique can be used to change OS/400 storage pools for any subsystem. You can allocate and reallocate storage pool memory for any configuration you can think of. This freedom gives you flexibility in allocating resources to your jobs.
Double, Double Toil and Trouble
There are a few tricks to OS/400 memory management. However, these tricks have their own troubles.
Storage pool memory adjustment is a delicate process. Take away too much memory and subsystem jobs choke, endlessly thrashing data into and out of memory in a vain attempt to finish processing. Give a storage pool too much memory and jobs in that system perform well, but memory is wasted that could be put to better use elsewhere. Care must be taken in determining storage pool allocations, or your system performance will suffer.
The mathematics of storage pool memory allocation is a complex subject and IBM gives many good tips on it in its Work Management Guide and other publications. However, there is one tool that attempts to tune your system for optimum performance by executing memory management automatically. The Performance Adjustment (QPFRADJ) system value can be set to make automatic adjustments to your storage pool memory allocations. When this parameter is set to '2' or '3', OS/400 will examine your system as it is running and change the storage pools and activity levels automatically to reflect the workload in your system.
The problem with this technique is that OS/400 is always adjusting the system to process events that occurred a few minutes ago. Between the time it analyzes your performance and the time it changes your storage pool values, the profile of jobs running in your system may have changed.
If you have a large job that temporarily thrashes, OS/400 will adjust your system to give more memory to the thrashing job by taking memory from another storage pool, such as *INTERACT. OS/400 makes this adjustment regardless of whether the job is still running. If the job ends between analysis and change time, OS/400 still changes the storage pool memory size. The next time the OS/400 makes an adjustment, it corrects for this problem, but it may make a different adjustment that is no longer valid.
QPFRADJ is a good technique to use if you have a fairly steady workload that doesn't change a lot. However, if your environment is more dynamic-where the memory and activity levels may need to be changed at a moment's notice-it can be a dangerous technique to use because the automatic adjustments will always be behind the times.
Another memory management technique is to create a private storage pool for a subsystem instead of using one of the predefined shared pools. Private pools are assigned to a single subsystem, and they cannot be shared with other subsystems.
Private pools take their memory directly from the *BASE storage pool. They use this memory directly for their own processing, not sharing it with any other subsystems. There is little difference between this technique and permanently assigning memory to a shared storage pool except that private pools allocate memory only when their associated subsystem is active. When the subsystem is inactive, its memory returns to *BASE and can be used for other jobs running out of *BASE. In cases where a subsystem is inactive most of the day, a private pool makes more sense as it does not permanently lock memory away from *BASE the way a shared pool does.
Private pools can be valuable in situations where different subsystems become active and shut down at different times of the day.
Going back to our example, to create a private pool to service QPGMR instead of assigning it to a shared pool, we would use this command:
CHGSBSD SBSD(QPGMR) + POOLS((1 800 1))
When you create a private pool in this manner, the new pool will show up on the Work with System Status (WRKSYSSTS) screen and *BASE's storage size will decrease accordingly. Your new private pool, however, will not show up on the WRKSHRPOOL screen. This is because the WRKSHRPOOL command only displays the 14 shared pools in your system. It does not show any private pools.
Parting Is Such Sweet Sorrow
We've barely scratched the surface of storage pool management. But with these basics-dividing memory and activity levels between storage pools, assigning storage pools to subsystems, creating private pools, and using the QPFRADJ subsystem value to automatically adjust your pools-you'll be well on your way to managing your own storage pools.
And if the result isn't really Shakespeare, at least you'll have a good memory management system.
Joe Hertvik is a freelance writer and a system administrator for a manufacturing company outside of Chicago.
REFERENCE
Work Management Guide (SC41-3306, CD-ROM QBKALG00).
Storage Pool Management of the AS/400
Figure 1 Viewing Storage Pool Allocation
UNABLE TO REPORDUCE GRAPHICS
Storage Pool Management of the AS/400
Figure 2 Storage Pools After Assigning 800K to *SHRPOOL1
UNABLE TO REPORDUCE GRAPHICS
Storage Pool Management of the AS/400
Figure 3 Subsystem Description Parameters
UNABLE TO REPORDUCE GRAPHICS
Storage Pool Management of the AS/400
Figure 4 QPGMR Set to Use *BASE
UNABLE TO REPORDUCE GRAPHICS
Storage Pool Management of the AS/400
Figure 5 QPGMR After Being Changed to *SHRPOOL1
UNABLE TO REPORDUCE GRAPHICS
LATEST COMMENTS
MC Press Online