HP 3000 Manuals

SEGMENTATION STRATEGIES [ MPE Segmenter Reference Manual ] MPE/iX 5.0 Documentation


MPE Segmenter Reference Manual

SEGMENTATION STRATEGIES 

Remember that, although the Segmenter is a powerful tool, most
programmers never need to access it explicitly.  In almost all
situations, the segmentation accomplished by the MPE operating system is
quite adequate.  If you decide to control or alter segmentation, it will
usually be for one of the following reasons:

 *  You are involved in program design and are testing different
    procedures or versions of a procedure.  Resegmenting or altering the
    contents of a segment gives you freedom to experiment without having
    to rewrite and recompile your source code.

 *  You have a problem to solve, such as the inadvertent duplication of
    an RL procedure name; or the use of an excessive number of RL
    references, resulting in an RL segment which exceeds your system's
    maximum configured code segment size.

The problems which would make altering segment contents or controlling
segmentation necessary (instead of optional, as it is with program
design) are relatively infrequent.

Because segmentation is so adequately handled by the operating system and
because problems with it are infrequent, your control of segmentation
will rarely have a significant impact on performance.  Resegmentation
will not help if you have major problems with your use of system
resources; and if you want a program with exceptional speed and
efficiency, a slight change in program logic or I/O structure will have
more effect than any amount or kind of resegmenting you can do.

Nevertheless, if you have chosen to control segmentation, you will want
to follow some guidelines to make your management as effective as
possible.  As you use the Segmenter, you will develop effective
strategies suited to your system and the kinds of programs you and other
programmers are writing.  However, there are some general guidelines you
can follow.  An understanding of some of the design characteristics of
the HP 3000 and of how the Segmenter works will help you to make
effective use of these guidelines and to develop your own strategies.

The Operating System Environment 

The Multiprogramming Executive (MPE) environment is a dynamic one where
programs are run on the basis of "processes".  A process is the basic
executable entity of MPE. It is not a program, but the unique execution
of a program by a particular user at a particular time.

When you execute a program, a private data segment called a "stack" is
created for that particular execution.  The stack and the program's code
segments together constitute the process, along with any external
references made by your program code.  For example, if several users
access the BASIC interpreter, a separate process is created for each of
them.  They all use the same code, since there is only one BASIC
interpreter; but each user has a unique data stack created by MPE.

Two MPE components have primary responsibility for managing process
execution:  the process dispatcher and the memory manager.  The
dispatcher allocates CPU time to all the executing processes.  The memory
manager's function is to fit code and data segments into main memory as
they are required.  This operation often requires the dispatcher to
decide which already-present segments it must delete in order to make
space available.

When the time-slice for your process begins, the stack and one code
segment are brought into main memory and control is passed to the
program.  As the program proceeds, it will call procedures which are not
in the current segment.  At this point your process is suspended while
MPE arranges to make the required segment present.  In the meantime, the
dispatcher tries to run the process with the next highest priority which
already has a data stack and any required code segments resident in
memory.  When the missing segment for the first process has been made
present, control is passed back to the procedure which called the
segment, and the second process is suspended.

There is no way for you to tell which code segments will be present in
main memory at any particular moment.  All you can be sure of is that the
memory manager will keep the most popular code segments available and
will overwrite those which are rarely used.  If a process needs an
overwritten segment, another copy of the segment will be brought in from
disc memory.  Frequently-used segments remain in main memory, while those
rarely used are in disc memory most of the time.

To you as a user, calling a procedure seems equally easy whether or not
it is in the current segment, since MPE handles process management
without your assistance.  However, there are system constraints which can
be aggravated by poor segmentation.  One of these is the physical size of
main memory, which limits the number of code segments which can be
present at any one time.  Another is the amount of time involved in
swapping absent segments in from disc memory:  while it may not be
noticeable to you, the time involved does affect the efficient use of
system resources and the execution of your process.  A third constraint
is that many processes are competing for CPU time, and a process which is
well-segmented will execute more smoothly, making better use of CPU time,
than one which makes many calls to procedures in absent segments.

Although processes themselves are created, maintained and deleted by MPE,
you do have control over the following process elements:

 *  Which code goes into which segment.

 *  The size of each segment.

 *  The number of code segments.

 *  The size of the data stack (which you control with the compiler
    rather than the Segmenter).

In almost all circumstances, the first element is the only one you need
to be concerned about:  although your programs are unlikely to approach
the segment size and number limitations, which code you place in each
segment can affect the amount of work the memory manager must do to make
code segments present in main memory for executing processes, thus
affecting how quickly and smoothly the CPU can handle your executing
program.

Segmentation Guidelines 

Your concerns for achieving good segmentation should focus on "locality",
which is the degree to which control remains in the same general area of
code.  This focus doesn't change even in systems with physical memory
space problems.  Indeed, locality becomes even more of a concern in such
systems.

ACHIEVE LOCALITY.  Poor locality means that a program branches wildly and
rapidly from place to place, so that when it is segmented and run, there
will be many external references and control will have to pass frequently
from segment to segment.  Inter-segment transfers which require control
to be passed to a segment not present in main memory are particularly
wasteful of time and disruptive to your process and other processes as
the memory manager reorganizes main memory to make space available for
the requested segment.

To work efficiently, the HP 3000 design needs programs that have good
segment locality.  Good segment locality exists when inter-segment
transfers are minimized:  that is, when a program is segmented so that
once the system is working within a particular segment, it stays there as
long as possible, and when it is out, it stays out as long as possible.
(Note that the degree of locality within a segment is not important.)

When they make segmentation decisions, most programmers intuitively feel
that they will achieve localization if they segment according to
function:  that is, they want to put all the command decoding procedures
together in one segment, all the command executors together in another
segment, and so on.  But you will achieve much better results if you
segment according to temporal considerations:  that is, consider how you
can group your procedures so that when your program is executing, the
system will be able to stay within each segment for as long as possible
and pass control smoothly from segment to segment as the program
progresses.

For example, consider a small utility program which dumps a file to the
line printer in some special format.  Suppose the operator can choose the
name of the file and which of those possible formats to use.  The program
has four procedures:  A, B, C, and D.

[]
Suppose, further, that each dump procedure has a procedure to fetch a record from its file and a procedure to format a print line:
[]
You would probably be tempted to put all the formatting routines in one segment and the record-fetching routines in another. But such functional segmentation would cause a segment boundary to be crossed twice for every record dumped. During this transfer time, your program is doing no useful work and other processes are disrupted, since they must wait for the CPU to finish with your process. If you segment temporally, however, with A in its own segment and B1/B2 together, C1/C2 together, etc., then only two segment boundaries are crossed for a whole dump. You can help achieve good locality by being careful, when you are altering or controlling segmentation, not to place in separate segments procedures which call each other. Even earlier, when you are designing your program and writing source code, being aware of how you divide your program into procedures will have an effect on how your code is segmented and thus, ultimately, on locality. It is possible to write programs that cannot be correctly segmented. For instance, any procedure or outer block must reside wholly within a segment. If it becomes necessary to move a block of code into another segment, it will only be possible if the code is a procedure: you cannot move an arbitrary set of instructions and place them in another segment but must move the whole RBM. You will also want to be aware of the conventions of your particular programming language for constructing RBMs from source code and compiling those RBMs into segments. Appendices A through F will provide you with some of the major conventions for each language. Refer to the appropriate language reference manual for more help. Routinely using the ;PMAP option when you prepare your programs will help keep you aware of each program's environment: the size of each segment, which procedures are in which segment, and the names of the externals called by each segment. Such information will help you minimize inter-segment transfers as well as to follow the other guidelines for code manipulation. You can find more detailed information about ;PMAP in Appendix G. ELIMINATE NON-ESSENTIAL MATERIAL FROM YOUR SEGMENTS. Minimizing the amount of unused material in any segment, file, account, etc., is a good general principle, as well as a way to reduce contention for memory resources. You can clean up segments by examining the code within them and removing code which executes only infrequently. Very often, this will be code which does error-handling. Instead of handling detected errors on-line, write an error-message generating procedure and call it with a parameter indicating which message to output. You can put this procedure in a separate segment so that it does not clutter up main memory while the system is doing normal, error-free processing of your program. As another example, suppose you have a program that does an FWRITE and then checks the condition code for end-of-file. If required, the program executes a somewhat elaborate sequence to extend the file by building a new one, copying the old one into it, and then purging the old file. If this condition is likely to occur only once in every 500 program runs, there is little point in holding the procedure in main memory with other procedures which do execute frequently. You can move this code to an auxiliary segment and let MPE bring it in only when it is needed. (Remember that you can only move such code out of a segment if it is a procedure in itself, rather than a series of instructions which are part of a procedure.) If your program will be run from multiple terminals, then the code segments will automatically be shared by the multiple processes, but each process will have its own data stack. If your program design requires data which is never altered, such as error messages, look-up tables, etc., put the data in your code so that only one copy will be required for all processes. Otherwise, all users who run the program will receive space in their data stack for the code, thus making inefficient use of main memory resources. In the following SPL program, the array MESSG is present in the stack of every process running the program. BEGIN BYTE ARRAY MESSGINIT (0:22):="TOO MANY TIMES ENTERED"; . . . PROCEDURE MESSOUT; BEGIN BYTE ARRAY MESSG (0:22) MOVE MESSG:=MESSGINIT,(23); PRINT (MESSG,-23,0); . . . END; . . . END. We will use main memory space more efficiently if MESSG only exists while MESSOUT executes. In the next example, SPL stores the string in quotes in the code segment. BEGIN . . . PROCEDURE MESSOUT; BEGIN BYTE ARRAY MESSG(0:22); MOVE MESSG:="TOO MANY VALUES ENTERED"; PRINT (MESG,-23,0); END; . . . END. This guideline and the accompanying examples illustrate the point that the steps you take to achieve good segmentation are not limited to moving material from segment to segment or altering material within segments. Rather, you need to keep in mind the Segmenter's function and the effect of segmentation on execution, even during phases of the program development process that precede the Segmenter's involvement. Obtaining Machine-Readable PMAPs: The FPMAP The Segmenter's PMAPs, produced by the PMAP option of the -PREPARE and -ADDSL commands and explained in Appendix G, are printed listings which show where a program's procedures are located in the code segments of a program or SL file. When you prepare a program file or SL segment, you may also request that a machine-readable form of the PMAP be stored in the program or SL file. This machine-readable form of the PMAP is known as the FPMAP. FPMAPs are useful to subsystems which wish to refer to code locations by procedure names and offsets within procedures, rather than by segment numbers and code segment addresses. For instance, they allow HP TOOLSET to set and interpret breakpoints based on source-code locations, and allow APS/ (SAMPLER) to break down program execution profiles by procedures rather than by arbitrary code segment addresses. There are two ways to control whether or not the Segmenter will generate FPMAPs with your program files or SL file segments. The first is explicit, and is done by including either the FPMAP or NOFPMAP keyword on a -PREPARE or -ADDSL command. The second is implicit, and involves the setting of the system-wide and job/session FPMAP flags with the -SETFPMAP command. These flags allow you to control FPMAP generation without using the FPMAP/NOFPMAP keywords on -PREPARE and -ADDSL commands, thereby providing a means for obtaining FPMAPs without modifying your existing Segmenter job or command files. SYSTEM-WIDE FPMAP FLAG. The system-wide FPMAP flag can be used to force FPMAPs in all program files and SL segments prepared on the system, and is also used to set the value of the job/session FPMAP option flag when a user logs onto the system. To set the system-wide FPMAP flag, you must have System Manager (SM) capability. The system-wide FPMAP flag may assume one of the following values: UNCONDITION Causes FPMAPs to be generated for all program files and (ON) SL segments prepared on the system, regardless of the setting of the job/session FPMAP flag or presence of the FPMAP/NOFPMAP keywords on -PREPARE and -ADDSL commands. This value also causes the job/session FPMAP flag to be initialized to ON at the beginning of each job and session. CONDITION (ON) Causes the job/session FPMAP flag to be initialized to ON at the beginning a job or session. OFF Causes the job/session FPMAP flag to be initialized to OFF at the beginning of a job or session. When a system is started or loaded, the system-wide FPMAP flag is initialized to OFF. JOB/SESSION FPMAP FLAG. Each job or session also has its own FPMAP flag, which controls FPMAP generation for -PREPARE and -ADDSL commands performed within that job or session as follows: ON Causes FPMAPs to be generated for all program and SL files prepared in the current job or session, unless overridden by the NOFPMAP keyword on -PREPARE and -ADDSL commands. OFF Inhibits FPMAP generation for all program and SL files prepared in the current job or session, unless overridden by either the system-wide FPMAP flag (if set to UNCONDITION (ON)), or the FPMAP keyword on -PREPARE and -ADDSL commands. For programs compiled by HP TOOLSET, the FPMAP will always be generated if symbolic debugging is requested, regardless of the FPMAP flags and FPMAP/NOFPMAP keywords. When preparing such programs, only the NOSYM keyword can suppress the FPMAP information. FPMAPs will increase program and SL file size by 3 to 10 percent, and will cause the CPU time for preparing a program file or SL segment to increase by 5 to 20 percent. Since the FPMAP information is not stored as part of the code segments themselves, it will have no effect on program execution performance. Because of the potential benefit of having the FPMAP information available for use by other subsystems, it is a good idea to include it with all program and SL files. Three intrinsics are provided for programmatic access to the FPMAP: FINDPMAPNAME translates segment names and procedure names to segment numbers and offsets; FINDPMAPADDR translates segment numbers and offsets to segment names and procedure names, and DUMPPMAP extracts the entire FPMAP from a program or SL file into an external file for use by other applications. Each of these uses the external FPMAP record format shown in Figure 3-1.
[]
Figure 3-1. External FPMAP Record Format Using the Application Program SAMPLER/3000 (APS/3000) APS/3000 is an interactive performance tool for tuning applications on the HP 3000. You may wish to use it to facilitate your identification and correction of segmentation problems. APS/3000 monitors the execution of software (a single program or the multiple execution of one or more shared program files) and produces histograms showing the amount of CPU time spent by various programs, or portions of one monitored program. You can study the histograms and then fine-tune your software by optimizing the execution time of: * All processes associated with a single program file. * A single process. * A segment. * A procedure. * An address range. In a typical application of this performance tool, the user runs and monitors software for a period of time, studies APS/3000's histograms, and learns which code consumes the most CPU time. After optimizing the code, the user repeats this process until the software performance is acceptable. For resegmentation purposes, APS/3000 will allow you to estimate the number of transfers of control between segments during program execution. Because it is a statistical sampling technique, APS/3000 assesses system operation at pre-set time intervals, rather than continually. Thus it will not provide the exact number of transfers, nor can it tell you specifically what to do to make your segmentation more efficient. However, it can offer you valuable help in identifying problem areas. You should always specify FPMAP when running APS/3000 since it automatically generates valuable information that can assist you in diagnosing program failures. For more information, see the Application Program SAMPLER/3000 (APS/3000) Reference Manual and User Guide (32180-90001).


MPE/iX 5.0 Documentation