CODING TECHNIQUES AND CONSIDERATIONS - IBM Mainframe

The performance of your program can generally be improved by careful use of coding techniques. Some of these techniques also have an influence on the actions the optimizer takes when trying to improve code efficiency. Careful consideration and implementation of these techniques will generally have a positive influence on your program's performance.

Programming Style

The coding style you use can, in certain circumstances, affect how the optimizer treats your code.

Structured Programming

The new structured programming statements, such as EVALUATE and in-line PERFORM, make the program more comprehensible and also generate a linear control flow. This allows the optimizer to operate over larger regions of the program. Avoid using the following constructs:

  • The ALTER statement
  • Backward branches (except as needed for loops for which PERFORM is unsuitable).
  • PERFORM procedures that involve irregular control flow; for example, a PERFORM procedure such that control cannot pass to the end of the procedure and thus cannot return to the PERFORM statement.

Use top-down programming constructs. Out-of-line PERFORM statements are a natural means of implementing top-down programming techniques. With the optimizer, out-of-line PERFORM statements can be as efficient as in-line PERFORM statements in many cases, since the linkage code may be simplified or eliminated altogether.

Factoring Expressions

Factoring can save a lot of computation; for example, this code:

Factoring Expressions

Symbolic Constants

If you want the optimizer to recognize a data item as a constant throughout the program, initialize it with a VALUE clause and do not modify it anywhere in the program. If you pass a data item to a subprogram BY REFERENCE, the optimizer considers it to be an external data item and assumes that it is modified at every subprogram call. If you move a literal to a data item, the optimizer recognizes it as a constant, but only in a limited region of the program following the MOVE statement.

Recognizing Constant Computations

When several items of an expression are constant, ensure that the optimizer is permitted to optimize them. For evaluating expressions, the compiler is bound by the left-to-right evaluation rules of COBOL. Consequently, either move all the constants to the left end of the expression, or group them inside parentheses. For example, given that VI, V2, and V3 are variable and that C1, C2, and C3 are constants, the expressions:

Recognizing Constant Computations

Often, in production programming, there is a tendency to place constant factors on the right-hand end of expressions. However, this can result in less efficient code because optimization is lost. Recognizing Duplicate Computations

When several components of different expressions are duplicates, make sure the compiler is permitted to optimize them. For evaluating arithmetic expressions, the compiler is bound by the left-to-right evaluation rules of COBOL. Consequently, either move all the duplicates to the left end of the expressions, or group them inside parentheses. Given that VI through V5 are all variable, the computation, V2 * V3 * V4, is a duplicate (known as a common sub-expression) between the following two statements:

Recognizing Constant Computations

Given that the optimizer can eliminate duplicate computations, there is no need for you to introduce artificial temporaries. The program is often more comprehensible without them.

Data Usage

In certain circumstances, the use of one data type over another can be more efficient. Consistent data type usage can reduce the need for conversions when performing operations on data items. Computational Data Items

When a data item is used mainly for arithmetic or as a subscript, specify USAGE BINARY on the data description entry for the item. The hardware operations for manipulating binary data are faster than those for manipulating decimal data. Note, however, that if a fixed-point arithmetic statement has intermediate results with a large precision (number of significant digits), the compiler will use decimal arithmetic anyway, after converting the operands to PACKED-DECIMAL form. For fixed-point arithmetic statements, the compiler will normally use binary arithmetic for simple computations with binary operands, if the precision remains at 8 digits or fewer. Above 18 digits, the compiler always uses decimal arithmetic. With a precision of 9 to 18 digits, the compiler nay use either form.

For a BINARY data item, the most efficient code is generated if the item has: A sign (S in its PICTURE clause) 8 digits or fewer. When a data item is used for arithmetic, but is larger than 8 digits or is also used with DISPLAY data items, then PACKED-DECIMAL is a good choice. The code generated for PACKED-DECIMAL data items can be as fast as that for BINARY data items in some cases, especially if the statement is complicated or specifies rounding.

For a PACKED-DECIMAL data item, the most efficient code is generated if the item has:

  • A sign (S in its PICTURE clause)
  • An odd number of digits (9s in the PICTURE clause), so that it occupies an exact number of bytes without a half-byte left over
  • 15 digits or fewer because a library routine call must be used to multiply or divide larger items.

Consistent Kinds of Data

When performing operations on operands of different types, one of the operands must be converted to the same type as the other. Each conversion requires several instructions. Also, a substantial amount of code may have to be executed to make operands conformable; for example, scaling one of the operands to give it the appropriate number of decimal places. This can largely be avoided by giving them both the same usage and also appropriate PICTURE specifications. That is, two numbers to be compared, added, or subtracted should not only have the same usage but also the same number of decimal places (9s after the V in the PICTURE clause).

Implications of External Data

External data items comprise every data item in the Linkage Section, together with any data items that are passed BY REFERENCE to subprograms. External data items also refer to any data items that are defined with the EXTERNAL clause, and also to external (UPSI) switches. Each level-01 data item in the Linkage Section is separately addressed. Consequently, the program must load a base register each time one of these data items is referenced. By contrast, you can reference each 4K block of data Items in the Working-Storage Section from the same base register. Also, the optimizer must assume that any called subprogram can modify any external data item and inhibit the optimization (across subprogram calls) of expressions containing external data items.

Coding Data Files

When using QSAM files, use blocking whenever possible (the BLOCK CONTAINS clause). When writing to variable-length blocked sequential files, use the APPLY WRITE-ONLY clause for the file or use the AWO compiler option. With AWO specified, APPLY WRITE-ONLY will be in effect for all files within the program that are physical sequential with V-mode records. This can reduce the number of calls to Data Management Services.

When using VSAM files, increase the number of data buffers for sequential access or index buffers for random access. Also, select a control interval size (CISZ) appropriate for the application (smaller CISZ results in faster retrieval for the random processing at the expense of inserts, whereas a larger CISZ is more efficient for sequential processing). If you use alternate indexes, using Access Method Services to build them is more efficient than using the AIXBLD run-time option. For better performance, access the records sequentially and avoid using multiple alternate indexes when possible.

Coding Data Types

Avoid using USAGE DISPLAY data items in areas that are heavily used for computations. When using COMP-3 data items in computations> use 15 or fewer digits in the PICTURE specification to avoid the use of library routines for multiplication and division. Plan the use of fixed-point and floating-point data types. Using indexes to address a table is more efficient that using subscripts because the index already contains the displacement from the start of the table and it does not have to be calculated at run time. When using subscripts (as opposed to indexes) to address a table, use a binary (COMP) signed data item with 8 or fewer digits. Additionally, in some cases, using 4 or fewer digits for the data item may also improve CPU time.

When using OCCURS DEPENDING ON (ODO) data items, ensure that the ODO objects are binary (COMP) to avoid unnecessary conversions each time the variable-length items are referenced. When using ODO data items, you may experience performance degradation since special code must be executed each time a variable-length data item is referenced. If you do use variable-length data items, copying them into a fixed-length data item prior to a period of high-frequency use can reduce some of this overhead.

Plan Use of Fixed-Point and Floating-Point Data Types

You can enhance program performance by carefully determining when to use fixed-point and floating-point data types.

Arithmetic Expressions

Computation of arithmetic expressions that are evaluated in floating-point mode are most efficient when the operands involved require the least amount of conversion. Using operands that are COMP-1 or COMP-2 produces the most efficient code. Integer items declared as BINARY or PACKED DECIMAL, with 9 or fewer digits, can be quickly converted to floating point. Also, conversion from a COMP-1 or COMP-2 item to a fixed-point integer with 9 or fewer digits, without SIZE ERROR in effect, is efficient when the value of the COMP-1 or COMP-2 item is less than 1,000,000.000.

Exponentiations

Exponentiations with large exponents can be evaluated more quickly and with more accurate results using floating-point. For example,

Exponentiations

Since the presence of a floating-point exponent would cause floating point to be used to compute the exponentiation.

Table Handling

Table handling operations can be a major part of an application. There are several techniques that can improve the efficiency of these operations and also influence the effects of the optimizer. Subscript Computations For the table element reference: ELEMENT(SI S2 S3) where SI, S2, and S3 are subscripts, the compiler must evaluate the following expression:

where:

  • compsl - The value of SI after conversion to binary, and so on.
  • dl, d2, and d3 - The strides for each dimension.

The stride of a given dimension is the distance in bytes between table elements whose occurrence numbers in that dimension differ by 1 and whose other occurrence numbers are equal. For example, the stride, d2, of the second dimension in the above example, is the distance in bytes between ELEMENT(S1 1 S3) and ELEMENT(S1 2 S3).

Although the expression could be evaluated in any order, the compiler evaluates it in left-to-right order. Thus, the optimizer will find the most opportunities for eliminating computations if the constant or duplicate subscripts are the leftmost. You can further optimize table element references by declaring any subscripts as COMP.

Recognizing Constant Subscript Computations

Assume that CI, C2,. . . are constant data items and that VI, V2, ... are variable data items. Then. for this table element reference:

ELEMENT(VI CI C2)

The compiler can eliminate only the individual terms compel * d2 and comp_c2 * d3 as constant from the expression:

However, for table element reference:

ELEMENT(CI C2 VI).

The compiler can eliminate the entire sub-expression compel * dl + comp_c2 * d2 as constant from the expression:

Consequently, try to use your tables so that constant subscripts are the leftmost subscripts. If all the subscripts are constant, then no subscript computation is done at object time, as in the following tab* element reference:

ELEMENT(CI C2 C3)

whose expression is:


With the optimizer, the reference can be as efficient as a reference to a scalar (nontable) item.

Recognizing Duplicate Subscript Computations

The same considerations for recognizing constant subscript computations apply to duplicate subscript computations. Given the following two table element references:

ELEMENT(VI V3 V4) ELEMENT(V2 V3 V4)

Only the individual terms comp_v3 * d2 and comp_v4 * d3 are common sub-expressions in the expressions needed to reference the table elements:

However, for these two table element references:

ELEMENT(VI V2 V3) ELEMENT(VI V2 V4)

The entire sub-expression comp_v1 * dl + comp_v2 * d2 is common between the two expressions needed to reference the table elements:

So, even when all the subscripts are variable, try to use your tables so that it is the rightmost subscript that varies most often for references that occur close to each other in the program. This will also improve the pattern of storage reference as well as paging.

If all the subscripts are duplicates, then the entire subscript computation is a common sub-expression, as in the two references:

ELEMENT(VI V2 V3) ELEMENT (VI V2 V3)

whose expressions are:

So, with the optimizer, the second (and any subsequent) reference to the same element can be as efficient as a reference to a scalar (nontable) item.

Recognizing Constant and Duplicate Index Computations

Index computations are similar to subscript computations, except that no multiplication needs to be done, since index values have the stride factored into them. The recommendations for optimizing subscripted references apply unchanged to indexed references. Index computations involve loading the indexes into registers, and these data transfers can be optimized, much as the individual subscript computation terms are optimized.

Tables with Identical Element Specifications

When subscripting or indexing different tables, it is most efficient if all tables have the same element length. With equal element lengths, the stride for the last dimension of the tables will be equal. The rightmost subscript or index computed for one table can then be reused by the optimizer for the others. So, consider defining tables to match the element length of the other tables with which they are involved.

If both the element lengths and the number of occurrences in each dimension are equal, then the strides for dimensions other than the last will also be equal, resulting in greater commonality between their subscript computations. The optimizer can then reuse subscripts or indexes other than the rightmost.

Indexing Preferred to Subscripting

The optimizer can eliminate duplicate subscript (and index) computations so that repeated references to an element of a table are equally efficient with subscripting and indexing. However, the original reference to a particular table element is more efficient with indexes than with subscripts, even if the subscripts are COMPUTATIONAL. This is because the value of an index has the element size factored into it, whereas the value of a subscript must be multiplied by the element size when the subscript is used.

Introduction of Artificial Indexing Temporaries

Relative indexing can be more efficient than direct indexing, so there is no merit in keeping alternative indexes with the offset factored in. This is because:

ELEMENT (I + 5, J - 3, K + 2) is no more costly than: ELEMENT (15, J3, K2)

Except that the second example requires this prerequisite processing:

SET 15 TO I SET 15 UP BY 5 SET J3 TO J SET J3 DOWN BY 3 SET K2 TO K SET K2 UP BY 2

Which makes the direct indexing less efficient than the relative indexing.

Implications of OCCURS DEPENDING ON (ODO)

A group item that contains a subordinate OCCURS DEPENDING ON data item has a variable length. The program must execute special code every time a variable-length data item is referenced. Because this code is out-of-line, it may interrupt optimization. Furthermore, the code to manipulate variable-length data items Is substantially less efficient than that for fixed-size data items and can result in a significant increase in processing time. For instance, the code to compare or move a variable-length data item may involve calling a library, routine, and is significantly slower than the equivalent code for fixed-length data items. To avoid unnecessary conversions when variable-length items are referenced, specify BINARY for OCCURS . . . DEPENDING objects. Copy variable-length data items into fixed-length data items prior to a period of high-frequency access.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

IBM Mainframe Topics