Anda di halaman 1dari 7

DO YOU KNOW ??

It is often noticed that there is some confusion regarding Static and Dynamic Calls
and considerable confusion regarding the pros and cons of these call types.

Let us try to clarify these calls...

When you use the CALL statement in a program that is compiled using the
NODYNAM compiler options, a STATIC CALL occurs. In the static CALL
statement, the COBOL program and all called programs are part of the same load
module. When control is transferred, the called program already resides in storage,
and a branch to it takes place.
Example : CALL “SUBPROG ” USING RECORD-1.

When you use the CALL statement in a program that is compiled using the DYNAM
compiler options or when you use the CALL identifier statement in a program, a
DYNAMIC CALL occurs. In this form of the CALL statement, the called COBOL
subprogram is not link-edited with the main program, but is instead link-edited into
a separate load module, and, at run time, is loaded only when it is required (that is,
when called).
Example : MOVE “SUBPROG ” TO PGM-NAME.
CALL PGM-NAME USING RECORD-1.
Where PGM-NAME is defined in the Working Storage Section.

Pros of dynamic linkage


 If the called subroutine is to be called by many, many programs and it is
"hard-linked" (static) into every single caller, if a change needs to be made
to it, you will need to find everywhere it is linked and re-link it.
 In many situations, a subroutine is never called due to the logic of the caller.
For example, a subroutine that calculates month-end totals might only be
called during a month-end run.
 Compiler run-times (modules that begin with "IGZ" in the case of COBOL)
must always be dynamic under the Language Environment. The point here is
that even if all your "CALL" statements are static, there is no way to make
the language run-times static (Note: In older COBOL compilers, this was
done with the RES/NORES compile-time option).

Cons of dynamic linkage


 More complex search paths. When a load module is entirely "packaged" by
the binder (linkage-editor), all external addresses are resolved. With
"dynamic" linkage, external addresses are not resolved, so "module not
found" abends (S806) might occur at run-time. This "con" is particularly
annoying in environments like TSO/ISPF where the average programmer has
a difficult time altering load module search paths (STEPLIB/JOBLIB). A
good idea is to use the "ON EXCEPTION" clause of the CALL to intercept
S806 abends if using dynamic CALLs.
 There is also the scope for increased I/O to JOBLIB but once a program
has been loaded, it will stay loaded unless explicitly removed via the COBOL
CANCEL statement.
 To get a dynamically CALLed subroutine to remain in a "first-called" state,
the "IS INITIAL" clause of the PROGRAM-ID statement is needed.

Pros of static linkage


 All linkage addresses resolved at link time. One big load module loaded.
Watch out for "UNRESOLVED EXTERNAL REFERENCE" (RC=8) from binder.
You will be hit with a certain S0C1 at run-time if "unresolved" address
encountered.
 This same thing---"one big load module"---simplifies search paths but makes
the initial load take longer (hardly matters usually).

Cons of static linkage


 Large load modules with potentially high internal CSECT duplication. In other
words, large, complex load modules.
 The "re-link" problem mentioned in "pros of dynamic".

Things to avoid
 Mixing the methods, using both dynamic and static. Confusing, if nothing
else.
 Coding the binder INCLUDE statement at SYSLIN when using dynamic
linkage.
 Using the COBOL CANCEL statement to force a reload of a previously
loaded program when using dynamic.

Finally, if you need to make both static and dynamic calls from your COBOL
program, compile with the NODYNAM option. In this case, with the CALL literal
statement the called subprogram will be link-edited with the main program into one
load module. The CALL identifier statement results in the dynamic invocation of a
separate load module.
What's new in COBOL for OS/390?
The biggest change you will notice in COBOL for OS/390 (also known as
COBOL/370 or COBOL for MVS) is that you can use "intrinsic functions". These are
special routines written to do specific things such as calculating the square root of
a number, generating a random number, changing a field to upper case characters,
and many other things.
For example:
COMPUTE WS-SQ1 = FUNCTION SQRT(WS-SQ2)
would calculate the square root of the number stored in WS-SQ2 and place it in
WS-SQ1.
Intrinsic functions are built in to COBOL (Note With some compliers you can even
write your own functions - check compiler documentation to see if this is
implemented).
COBOL for OS/390 is Y2K compliant.
COBOL for OS/390 introduces a new feature known as Procedure Pointer fields.
These are pointers to the Program-ID of a non-nested COBOL program, the entry
point of a COBOL program or an entry point to a non-COBOL program.
To define a procedure pointer field you specify USAGE IS PROCEDURE-POINTER
or PROCEDURE-POINTER. You should not code a PIC clause on the definition. You
can assign a value to the procedure-pointer using SET. To pass the procedure
pointer to another program you CALL the program USING the procedure pointer
field.
(CICS/COBOL users may be familiar with pointers, which are used to point to
storage addresses for data items. Although Procedure Pointers follow similar rules
the two types of pointer are different should not be confused.)

What's the difference between GOBACK and EXIT PROGRAM?


GOBACK and EXIT PROGRAM both allow you to specify an exit point from a
COBOL program, usually they are used to exit a program that has been CALLed
from another program . Normally you won't notice any difference between the two
methods of leaving a program.
When GOBACK or EXIT PROGRAM is executed in a CALLed program control is
returned to the CALLing program.
The difference occurs when EXIT PROGRAM appears in a program that has not
been CALLed by another program. In this case the EXIT PROGRAM is ignored, and
processing continues. This can cause all sorts of problems, so you should use
GOBACK instead of EXIT PROGRAM.

How can I improve program performance?


There are various methods of improving the efficiency of your code from the way
you code your program to the compiler options you choose. Some of these
techniques will not make any major difference to speed unless you are processing
high volumes of data and/or code is going to be executed millions of times for each
run. The points presented below are guidelines only - there may be better ways of
speeding things up - if you are worried about performance, it is always a good idea
to discuss it with your local systems programmer.

1) Arithmetic. Some arithmetical calculations take longer than others. Multiplication


and division take longer than adding or subtracting. So instead of, say multiplying a
number by 2 , try adding the number to itself. If you want to make a number
negative, you could subtract it from 0, instead of multiplying it by -1. Check all
arithmetic to see if there is a more efficient way of doing it

2) Order of comparisons. The way you do comparisons on an IF or EVALUATE


statement can affect performance. If you have multiple OR conditions on your IF
statement try and make sure that the condition most likely to be true is first in the
list. This means that the program will not have to check as many conditions before
finding a 'true' one.
Here's an example to illustrate this. In the example we are checking a VSAM
status code. The most likely value is 00 (Executed without any errors).
We could code:
IF WS-STATUS = '97' OR '96' OR '95' OR '00'
DISPLAY WS-STATUS.
The program would first check is WS-STATUS = '97', then it would check is WS-
STATUS = '96' then it would check is WS-STATUS = '95' and finally it would
check is WS-STATUS = '00', which would be true so the DISPLAY would be
executed. That would be four checks before the 'true' condition was found.
If we code:
IF WS-STATUS = '00' OR '97' OR '96' OR '97'
DISPLAY WS-STATUS.
then the program would check is WS-STATUS = '00'first, which is true so the
DISPLAY would be executed, with just one check.
Conversely if you have multiple AND conditions on your IF statement try and make
sure that the condition least likely to be true is first in the list. This means that
the program will bomb out of checking conditions as early as possible.

3) Watch those compiler options. Some compiler options can result in longer running
times. For example SSR, which checks for subscripts going out of range actually
adds extra code to your program to check subscripts. SSR would be acceptable in a
test environment, but may not be appropriate in the production environment.

4) Sorting. If at all possible avoid doing a sort within a COBOL program. COBOL
sorts are very inefficient. If you must do a sort in a COBOL program, specifying
the FASTSRT compiler option may speed up the sorting process.

5) Numbers.
a) How you define numeric fields can have an impact on performance. If you are
using a field for arithmetic or as a subscript and the field has 8 or fewer digits it is
quite often best to define it as a binary number (COMP-1) that is signed. This is
because binary numbers can be manipulated much faster. If the field has between 8
and 15 digits then it is often best to define it as a Packed decimal number (COMP-
3) with an odd number of digits and signed especially if the number is to be used
with USAGE DISPLAY items. If the number has more than 18 digits then decimal
arithmetic is always used by the compiler. For more information on this check out
the appropriate COBOL Application Programming Guide. Use signed numbers
wherever possible. COBOL does all arithmetic with signed numbers, so if you use
unsigned numbers COBOL has to add code to remove signs.
b) Rounding numbers can often take longer than the calculation so try to avoid
rounding numbers.
6) CALLs to other programs. When calling a subprogram with USING try to specify
as few parameters as possible. Each parameter passed requires an individual BLL
cell to be allocated in the called program and may require additional registers to be
used.
7) PERFORMs. If you do a 'PERFORM paragraph' the compiler may convert this
into up to six machine instructions. This is because the compiler must establish
where it is to jump to and save the address of the instruction to jump back to at
the end of the performed paragraph. PERFORMs with VARYING will require many
more machine instructions. This will probably only be a problem if the code is
executed millions of times. You should weigh up the pros and cons of maintainability
with speed. It might be better to opt for writing the program in Assembler if the
speed of execution is going to be a problem.

How Do I Use Evaluate?


I still get asked about using EVALUATE quite a lot, especially using multiple
conditions on EVALUATE statements, so here are some quick pointers to using this
statement.
EVALUATE can be used in place of IF statements, it can often make the program
more readable when you have complex nested conditions.
In it's simplest form the EVALUATE statement goes something like this:
EVALUATE condition
WHEN value
imperative-statements
WHEN value
imperative statements
...........
END-EVALUATE.

Here's a simple example:

EVALUATE WS-X
WHEN 1
ADD 15 TO WS-TOTAL
PERFORM A-100-REPORT
WHEN 2
ADD 16 TO WS-TOTAL
MOVE 'WS-X IS 2' TO WS-DISPLAY
PERFORM A-200-REPORT
WHEN OTHER
PERFORM X-100-ERROR
END-EVALUATE.

This will check the value of the variable WS-X and execute the statements
depending on the value. Note the use of WHEN OTHER this will be executed if
WS-X does not match any of the values, so in the example if WS-X is not equal to 1
or 2 then PERFORM X-100-ERROR will be executed.
Sometimes you will want to have multiple conditions with lots of ANDs and ORs in
an EVALUATE statement as you would in an IF statement. To do this with
EVALUATE requires a slightly different approach. One way is to use EVALUATE
TRUE (or EVALUATE FALSE). for example

EVALUATE TRUE
WHEN WS-X = 1 AND WS-Y = 2
PERFORM X-100-PROCESS1
WHEN WS-X =1 AND WS-Y NOT = 2
PERFORM X-200-PROCESS2
END-EVALUATE.

Here, the whole condition on the WHEN statement is checked and if it is TRUE
then the associated statement(s) are executed.
The second way to do this is using EVALUATE ... ALSO.

EVALUATE WS-AGE ALSO WS-SEX ALSO WS-WEIGHT


WHEN 21 ALSO 'M' ALSO 150
PERFORM A-200-ACCEPT
WHEN OTHER
PERFORM A-300-DECLINE
END-EVALUATE.

In this example if WS-AGE is 21 AND WS-SEX is 'M' AND WS-WEIGHT is 150


then PERFORM A-200-ACCEPT is executed, if not then PERFORM A-300-DECLINE
is executed.
You can combine ALSO with the TRUE and FALSE conditions, so you could have
EVALUATE TRUE ALSO FALSE for example.

How can I get the date a program was compiled?


If you want to get the date of compilation of a program (for example you may want
to display it to ensure you are using the correct version of the program), then you
can use the special register WHEN-COMPILED. This returns the date and time of
compilation as a 16 character string formatted as MM/DD/YYhh.mm.ss . You cannot
modify the WHEN-COMPILED register.
MOVE WHEN-COMPILED TO WS-COMP-DATE.
If you are using COBOL for OS/390 then you can also use the intrinsic function
WHEN-COMPILED to get the compile date. This returns a 21 character string, but
only the first 16 characters are used. The string is in the format
YYYYMMDDhhmmsszz (where zz is hundredths of a second)
MOVE FUNCTION WHEN-COMPILED TO WS-COMP-DATE.

Anda mungkin juga menyukai