MVS TOOLS AND TRICKS OF THE TRADE January 1995 Sam Golob MVS Systems Programmer sbgolob@cbttape.org Sam Golob is a Senior Systems Programmer working in New York City. ON FINDING PROGRAMS - BLDL AND LLA. One of the known inefficiencies in MVS processing has always been the disk file lookup. Even more clumsy disk-wise, is the process of finding a member of a partitioned dataset on disk. Add to that, a PDS directory search of a library with several thousand members. Finally, concatenate a good number of these libraries, and try to find a random member from the concatenation. The result is an extremely inefficient process, to say the least. Yet, this process is not only an everyday occurrence on MVS systems, it is repeated thousands upon thousands of times during a day's work. Without extra assistance, this very same action would occur every single time the system fetches a program from a linklist library on disk. That is because the system link list is usually a big concatenation of many sizable partitioned datasets. The first member of the concatenation, by definition SYS1.LINKLIB, normally contains several thousand programs as shipped by IBM. At the old MVS/370 level, IBM itself provided very little assistance in the quickening of program searches. Substantial help from IBM, which was its first version of LLA (then called Linklist Lookaside), only started with MVS/XA, as we shall describe. Nowadays on MVS/ESA systems, the component called the Contents Supervisor, running LLA (Library Lookaside), improves this situation very much. Program searches have become far more efficient than previously, if LLA is running. But even on an MVS/ESA system, if you issue the system command "P LLA" or "STOP LLA", you're back at square one, as we mentioned above. Some of this month's talk will be about LLA. However, before talking about LLA, I'd like to look at this general problem in a historical context. I definitely know that even now, there are shops still running MVS/370 and MVS/XA in daily production. And even for MVS/370 shops, there is good help available to speed up program searches, as we shall see. I don't think it's fair not to show these "older shops" what they can do too. A SHORT HISTORY OF THE "PROGRAM FETCH" PROBLEM. On the old MVS/370 systems, before the 31-bit addressing days, the only help in this area was a fixed list of link-listed programs in SYS1.PARMLIB (member IEABLDxx) called the "BLDL List". The BLDL list caused an in-storage table to be built at IPL time, with exact disk locations of the specific listed programs, so that a direct disk lookup could fetch these programs immediately. Thus, our long process of PDS directory searching in the link list libraries would be avoided for those programs. Problems with the BLDL List were: It would only perform its "efficiencies" for a fixed list of programs. That list was unalterable until the next IPL; you couldn't add other programs to it. You also couldn't use a new version of any program on the BLDL List, unless you would STEPLIB to the library containing the program. The only other alternative would be to ZAP the program in its place, which isn't always practical or possible. If a link-listed library containing these programs accidentally got compressed or moved, the system couldn't find the programs whose location had moved. There was no recourse or recovery except to IPL. If those lost programs were important enough, the system would slowly die. I know. I've caused it to happen once (many years ago), and one lesson like that is a lesson for a lifetime. For MVS/370, and even for MVS/XA, the users created a better solution called "Dynamic BLDL". Dynamic BLDL worked by hooking into SVC 18 (IGC018) which is the SVC that does program location lookups. Instead of using the system's fixed BLDL table, Dynamic BLDL would build a dynamically maintained in-storage table of link list programs that were most recently used, with their exact disk locations. The first time a program was fetched, Dynamic BLDL would add its location information to the dynamic table. Subsequent fetches would use the table instead of doing a long directory search. Since the table was dynamically created and was refreshable, you didn't have to IPL when a program's disk location moved. You just had to recycle Dynamic BLDL, and a new table-build would then be started. The most "modern" version of Dynamic BLDL was created by Dave Cole, with XA extensions by John Williams and Jeff Broido. This version of Dynamic BLDL can be found on the CBT MVS Tape, File 407. The CBT Tape may be ordered through NaSPA. If you're still running MVS/370 or even MVS/XA, Dynamic BLDL will definitely be useful to you. One of the advantages of Dynamic BLDL, which has not been addressed by IBM in its own later developments, is in the area of reporting. Dynamic BLDL will report on every program in the link list that was used most recently by the system. The report shows the number of times the program was fetched, what library in the link list the program came from, and how recently the program was used last. It is really three reports in one, with the program names sorted three different ways. Dynamic BLDL is useful even nowadays, under the following conditions: If you are still running MVS/370, Dynamic BLDL will very noticeably increase program fetch efficiency. Remember to remove all program names from the BLDL list (IEABLDxx) in SYS1.PARMLIB, and IPL before starting Dynamic BLDL for the first time. If you are running MVS/XA, you may find Dynamic BLDL useful for its report. LLA will interfere with Dynamic BLDL on MVS/XA, so you must stop LLA in order for Dynamic BLDL to be effective. After Dynamic BLDL has run for a while, run Dynamic BLDL's report, and then turn LLA back on. You may want to do this during different times of the day, or for one 24-hour period. The result will be a thorough survey of which programs the system has used most frequently (including "called" programs). WHAT'S DOING ON MORE "MODERN" SYSTEMS? Nowadays, first on MVS/XA and then further on MVS/ESA, IBM has created a far better method of fetching programs from disk. There actually is a system component, called the Contents Supervisor, that handles this task. There is a separate address space in which the Contents Supervisor does much of its work, and that address space is called "LLA". LLA means different things for different system levels. In MVS/XA, LLA stood for "Linklist Lookaside". On MVS/ESA, its function has been very widely extended, so the name now stands for "Library Lookaside". The idea of LLA is that a big table of program directory entries is put into a separate address space, and when a program is needed from disk, this table is efficiently consulted to find the exact location of that program on disk. Then the program "fetch" service goes to that location, gets the program, and loads it into storage. All PDS directory searching is avoided. This service has been extended to ALL programs residing on the link list, and not to just a subset of them. In MVS/ESA, the service can also include load libraries other than those on the system link list. LLA works well, compared to previous systems. I once benchmarked LLA on an MVS/XA system against Dynamic BLDL on XA, and it worked somewhat faster than Dynamic BLDL for a sample set of program lookups. In any case, the rest of this discussion will concern the practical treatment of programs residing in libraries that are under LLA control. SUBSTITUTING PROGRAMS UNDER LLA. When you change a program under LLA control, you have to know what is happening, to accurately predict the results. LLA tells you where the program resides on disk. If you load a new copy into the PDS on disk, the new copy will go to a different place on the disk (a different TTR location into the dataset). LLA knows about the original disk location only, so it will obviously not find the changed member. LLA will continue to use the old version of that program. However, suppose you ZAP (or change some of the contents of) the program at its existing disk location. The next time the system "fetches" the program from that location, you'll obviously get the changed version, because the starting disk location of the program hasn't been altered. If the old version of the program has been loaded into an address space's Job Pack Area, the old version is in storage, and it might be used a while longer. But the next time a fetch is done from disk, the zapped version will be executed. Now all this discussion has only considered changes to the programs on disk themselves. We have not yet talked about how to alter the LLA tables which reference these disk locations. How can the LLA tables themselves be changed? The brute force method is to issue the operator command: "F LLA,REFRESH", which completely re-initializes all LLA tables for all programs in all disk libraries that are under LLA control. This may take from 20 seconds to a minute on most systems. One might think it's a good thing to do this whenever some program on the link list is changed. In fact, "refreshing LLA" was a normal practice on MVS/XA. However on MVS/ESA, if you are using VLF (Virtual Lookaside Facility) to "stage" CLISTs and other structures in expanded storage, all of these CLISTs are de-staged when LLA is REFRESHed by operator command. Considerable system efficiency is lost for a long while. Therefore, it would seem advisable to more selectively refresh individual members or libraries on LLA, rather than to redo the whole thing every time. As far as refreshing individual libraries is concerned, what you do is to create a SYS1.PARMLIB member called CSVLLAxx, specifying the FREEZE and UNFREEZE of whatever libraries you want to control or de-control. Then you issue a system command: "F LLA,UPDATE=xx" to activate the PARMLIB member. All this is described in the MVS/ESA Initialization and Tuning Reference manual, and I will not talk about it any more here, because you can look it up. The rest of our discussion will concern the substitution of a new version of one individual program into the LLA tables. IBM's current official mechanism for this is called the LLACOPY service. LLACOPY is invoked via an assembler macro. THE LLACOPY SERVICE. The LLACOPY macro (in SYS1.MACLIB) is intended to substitute new versions of a list of programs into the LLA tables. The list is specified in a similar manner to the way a list of programs is presented to the BLDL macro. See Figure 1 for the format of the LLACOPY macro. Once the LLACOPY macro is coded into a program, this is how it works: First, the macro checks for the system level. If the system level is less than MVS/ESA 3.1, the program just issues a straight BLDL, and nothing is refreshed in LLA. This could present a problem, because the macro does not report such a condition to the program calling it. Nevertheless, if the system level is high enough, the macro formats its parameters, and then issues a PC call to the CSVLLCPY routine, which performs the LLA table substitution that is required. You may want to see a coding example. A practical example can be found on the CBT MVS Tape File 166 from my friend Vinh Vu. The member name on his file is called $LLACOPY, and his program's name is called LLACOPY. Vinh's program runs in batch, uses a PARM, and refreshes one program in the LLA tables from a disk library. The coding is relatively simple and easy to follow. I'd suggest that you get a CBT Tape and look at the code yourself. I've illustrated how to use Vinh's program in the JCL in Figure 2, and that figure is quite descriptive of what happens. It's time to say, "so long for now". Efficiency in program lookups has long been a sore point in MVS processing, so I felt that a discussion of what you can do, whatever your system level, might be in place. I hope it helps. See you next month. * * * * * * * * * * * * * * * * * * * * * * * Figure 1. Format of the LLACOPY macro. The LLACOPY macro may be found in SYS1.MACLIB on an MVS/ESA system. &XLABEL LLACOPY &DCB=,&BLDLLIST=,&RETCODE=,&RSNCODE=,&MF= * * * * * * * * * * * * * * * * * * * * * * * Figure 2. The following is JCL to run Vinh Vu's LLACOPY program. The JCL is quite descriptive of what the program is supposed to do. //$VNV3 JOB (acctg-params),VINH,MSGCLASS=Q,CLASS=B,NOTIFY=&SYSUID //* //STEP0 EXEC PGM=LLACOPY,PARM='ASREXIT' <=== PARM="module name" //STEPLIB DD DSN=$VNV.LOAD,DISP=SHR <=== Your APF loadlib //LLAPDS DD DSN=SYS1.LINKLIB,DISP=SHR,UNIT=SYSDA,VOL=SER=SYSPAK //SYSUDUMP DD SYSOUT=*