Showing posts with label Performance Tuning.. Show all posts
Showing posts with label Performance Tuning.. Show all posts

Sunday, 11 August 2013

COBOL Run-Time Performance Part 1

Selecting the proper run-time options is another factor that affects the performance of a COBOL application.
Therefore, it is important for the system programmer responsible for installing and setting up the LE environment to work with the application programmers so that the proper run-time options are set up correctly for your installation.
Let's look at some of the options that can help to improve the performance of the individual application, as well as the overall LE run-time environment.
AIXBLD : The AIXBLD option allows alternate indexes to be built at run time. However, this may adversely affect the run-time performance of the application. It is much more efficient to use Access Method Services to build the alternate indexes before running the COBOL application than using the NOAIXBLD run-time option. Note that AIXBLD is not supported when VSAM datasets are accessed in RLS mode.
ALL31 : The ALL31 option allows LE to take advantage of knowing that there are no AMODE(24) routines in the application. ALL31(ON) specifies that the entire application will run in AMODE(31). This can help to improve the performance for an all AMODE(31) application because LE can minimize the amount of mode switching across calls to common run-time library routines. Additionally, using ALL31(ON) will help to relieve some below the line virtual storage constraint problems, since less below the line storage is used.
CHECK : The CHECK option activates the additional code generated by the SSRANGE compiler option, which requires more CPU time resources for the verification of the subscripts, indexes, and reference modification expressions. Using the CHECK(OFF) run-time option deactivates this code but still requires some additional CPU time resources at every use of a subscript, index, or reference modification expression to determine that this check is not desired during the particular run of the program. This option has an effect only on a program that has been compiled with the SSRANGE compiler option.
DEBUG : The DEBUG option activates the COBOL batch debugging features specified by the USE FOR DEBUGGING declarative. This may add some additional overhead to process the debugging statements. This option has an effect only on a program that has the USE FOR DEBUGGING declarative.
RPTOPTS : The RPTOPTS option allows you to get a report of the run-time options that were in use during the execution of an application. This report is produced after the application has terminated. Thus, if the application abends, the report may not be generated. Generating the report can result in some additional overhead. Specifying RPTOPTS(OFF) will eliminate this overhead.
RPTSTG : The RPTSTG option allows you to get a report on the storage that was used by an application. This report is produced after the application has terminated. Thus, if the application abends, the report may not be generated. The data from this report can help you fine tune the storage parameters for the application, reducing the number of times that the LE storage manager must make system requests to acquire or free storage. Collecting the data and generating the report can result in some additional overhead. Specifying RPTSTG(OFF) will eliminate this overhead.
RTERUS : The RTEREUS option causes the LE run-time environment to be initialized for reusability when the first COBOL program is invoked. The LE run-time environment remains initialized (all COBOL programs and their work areas are kept in storage) in addition to keeping the library routines initialized and in storage. This means that, for subsequent invocations of COBOL programs, most of the run-time environment initialization will be bypassed. Most of the run-time termination will also be bypassed, unless a STOP RUN is executed or unless an explicit call to terminate the environment is made (Note: using STOP RUN results in control being returned to the caller of the routine that invoked the first COBOL program, terminating the reusable run-time environment).
Because of the effect that the STOP RUN statement has on the run-time environment, you should change all STOP RUN statements to GOBACK statements in order to get the benefit of RTEREUS. The most noticeable impact will be on the performance of a non-COBOL driver repeatedly calling a COBOL subprogram (for example, an assembler driver that repeatedly calls COBOL applications). The RTEREUS option helps in this case. However, using the RTEREUS option does affect the semantics of the COBOL application: each COBOL program will now be considered to be a subprogram and will be entered in its last-used state on subsequent invocations (if you want the program to be entered in its initial state, you can use the INITIAL clause on the PROGRAM-ID statement).
STORAGE : The first parameter of this option initializes all heap allocations, including all external data records acquired by a program, to the specified value when the storage for the external data is allocated. This also includes the WORKING-STORAGE acquired by a RENT program (unless a VALUE clause is used on the data item) when the program is first called or, for dynamic calls, when the program is canceled and then called again. Storage is not initialized on subsequent calls to the program. This can result in some overhead at run time depending on the number of external data records in the program and the size of the WORKING-STORAGE section.

Created with Artisteer

COBOL Feature Affect Run Time Performace

COBOL and Language Environment have several installation and environment tuning features that can enhance the performance of your application. We will now look at some additional factors that should be considered for the application.
Storage Management Tuning
Storage management tuning can reduce the overhead involved in getting and freeing storage for the application program. With proper tuning, several GETMAIN and FREEMAIN calls can be eliminated. To better understand the need for storage tuning, let's look at how storage management works.
First of all, storage management was designed to keep a block of storage only as long as necessary. This means that during the execution of a COBOL program, if any block of storage becomes empty, it will be freed.
This can be beneficial in a transaction environment (or any environment) where you want storage to be freed as soon as possible so that other transactions (or applications) can make efficient use of the storage. However, it can also be detrimental if the last block of storage does not contain enough free space to satisfy a storage request by a library routine. For example, suppose that a library routine needs 2K of storage but there is only 1K of storage available in the last block of storage. The library routine will call storage management to request 2K of storage.
Storage management will determine that there is not enough storage in the last block and issue a GETMAIN to acquire this storage (this GETMAINed size can also be tuned). The library routine will use it and then, when it is done, call storage management to indicate that it no longer needs this 2K of storage.
Storage management, seeing that this block of storage is now empty, will issue a FREEMAIN to release the storage back to the operating system. Now, if this library routine or any other library routine that needs more than 1K of storage is called often, a significant amount of CPU time degradation can result because of the amount of GETMAIN and FREEMAIN activity.
Storage Tuning User Exit
In an environment where Language Environment is being initialized and terminated constantly, such as CICS, IMS, or other transaction processing type of environments, tuning the storage options can improve the overall performance of the application. This helps to reduce the GETMAIN and FREEMAIN activity. The Language Environment storage tuning user exit is one way that you can manage the task of selecting the best values for your environment. The storage tuning user exit allows you to set storage values for your main programs without having to linkedit the values into your load modules.

Calling IGZERRE
One way that an assembler program can set up a reusable run-time environment for COBOL is by calling IGZERRE. This module can be invoked to explicitly initialize and terminate COBOL's portion of the LE run-time environment. It allows a non-COBOL, non-LE-conforming program to initialize the LE run-time environment, thereby effectively establishing itself as the main COBOL program. As a result, the use of STOP RUN will cause control to be returned to the caller of the routine that invoked the IGZERRE initialization. IGZERRE is an enhanced version of ILBOSTP0 (for OS/VS COBOL) and accomplishes the same  results as ILBOSTP0. Although, IGZERRE has been designed for Enterprise COBOL, COBOL for OS/390 & VM, COBOL for MVS & VM, COBOL/370, and VS COBOL II applications, it also supports OS/VS COBOL applications. Using IGZERRE has the added benefits of supporting applications running above the 16 MB line, allowing the application to terminate the COBOL portion of the LE run-time environment and improving the performance of the application Using ILBOSTP0 in an LE environment will set up both the OS/VS COBOL and the COBOL portion of the LE environments whereas using IGZERRE will set up only the COBOL portion of the LE environment (the OS/VS COBOL environment will be set up only as needed).

Created with Artisteer

COBOL Efficient Coding Techniques Part - 1.

Coding Technique is one of the most important factor that can fine tune application performace. Eventially it individual program performace that contribute toward entire application performace. When program is desgin efficently running cost would be low for entire project.
This section focuses on how the source code can be modified to tune a program for better performance. Coding style, as well as data types, can have a significant impact on the performance of an application.
Producing higher performing code usually has a far greater impact than that of tuning the application via compiler and run-time options, but producing such code may not be a viable option for many existing applications since it does require modifying the source code and at times may even require an extensive knowledge of how the program works. However, these techniques should be considered for all new applications.
  • Data Files : Planning how the files will be created and used is an important factor in determining efficient file characteristics for the application. Some of the characteristics that affect the performance of file processing are: file organization, access method, record format, and blocksize. Some of these are discussed in more detail below.
QSAM Files : When using QSAM files, use large block sizes whenever possible by using the BLOCK CONTAINS clause on your file definitions (the default with COBOL is to use unblocked files). If you are using DFP Version 3 Release 1 or later, you can have the system determine the optimal blocksize for you by specifying the BLOCK CONTAINS 0 clause for any new files that you are creating and omitting the BLKSIZE parameter in your JCL for these files. This should significantly improve the file processing time (both in CPU time and elapsed time). 
Additionally, increasing the number of I/O buffers for heavy I/O jobs can improve both the CPU and elapsed time performance, at the expense of using more storage. This can be accomplished by using the BUFNO subparameter of the DCB parameter in the JCL or by using the RESERVE clause of the SELECT statement in the FILE-CONTROL paragraph. Note that if you do not use either the BUFNO subparameter or the RESERVE clause, the system default will be used.
Variable-Length Files : When writing to variable-length blocked sequential files, use the APPLY WRITE-ONLY clause for the file or use the AWO compiler option. This reduces the number of calls to Data Management Services to handle the I/Os. For performance considerations using the APPLY-WRITE-ONLY clause or the AWO compiler option.
VSAM Files : When using VSAM files, increase the number of data buffers (BUFND) for sequential access or index buffers (BUFNI) for random access. Also, select a control interval size (CISZ) that is appropriate for the application. A smaller CISZ results in faster retrieval for random processing at the expense of inserts, whereas a larger CISZ is more efficient for sequential processing.
 In general, using large CI and buffer space VSAM parameters may help to improve the performance of the application. In general, sequential access is the most efficient, dynamic access the next, and random access is the least efficient. 
However, for relative record VSAM (ORGANIZATION IS RELATIVE), using ACCESS IS DYNAMIC when reading each record in a random order can be slower than using ACCESS IS RANDOM, since VSAM may prefetch multiple tracks of data when using ACCESS IS DYNAMIC. 
ACCESS IS DYNAMIC is optimal when reading one record in a random order and then reading several subsequent records sequentially.
Random access results in an increase in I/O activity because VSAM must access the index for each request. If you use alternate indexes, it is more efficient to use the Access Method Services to build them than to use the AIXBLD run-time option. 
Avoid using multiple alternate indexes when possible since updates will have to be applied through the primary paths and reflected through the multiple alternate paths.


Created with Artisteer

COBOL Efficient Coding Techniques Part - 2.

Data Types : Using the proper data types is also an important factor in determining the performance characteristics of an application. Some of these are discussed below.

  • BINARY (COMP or COMP-4)

When using binary (COMP) data items, the use of the SYNCHRONIZED clause specifies that the binary data items will be properly aligned on halfword, fullword, or doubleword boundaries. 

This may enhance the performance of certain operations on some machines. Additionally, using signed data items with eight or fewer digits produces the best code for binary items. The following shows the general performance considerations (from most efficient to least efficient) for the number of digits of precision for signed binary data items (using PICTURE S9(n) COMP) using TRUNC(OPT):

n is from 1 to 8 for n

from 1 to 4, arithmetic is done in halfword instructions where possible for n 

from 5 to 8, arithmetic is done in fullword instructions where possible 

n is from 10 to 17 

arithmetic is done in doubleword format 

n is 9 

fullword values are converted to doubleword format and then doubleword arithmetic is used (this is SLOWER than any of the above) 

n is 18 

doubleword values are converted to a higher precision format and then arithmetic is done using this higher precision (this is the SLOWEST of all for binary data items)

  • COMP-5 : Binary COMP-5 data items are similar to the above BINARY (COMP and COMP-4) data items with the exception that they always behave as if the TRUNC(BIN) compiler option were in effect for them. Hence, the performance recommendations for BINARY (COMP or COMP-4) data items also apply for COMP-5 data items.

Performance considerations for COMP-5:  

 using 1 to 4 digits is the fastest  

 using 5 to 9 digits is 35% slower than using 1 to 4 digits.  

 using 10 to 18 digits is 2200% slower than using 1 to 4 digits.

  • Data Conversions : Conversion to a common format is necessary for certain types of numeric operations when mixed data types are involved in the computation. This results in additional processing time and storage for these conversions. In order to minimize this overhead, it is recommended that the guidelines discussed below be followed.


  • DISPLAY : Avoid using USAGE DISPLAY data items for computations (especially in areas that are heavily used for computations). When a USAGE DISPLAY data item is used, additional overhead is required to convert the data item to the proper type both before and after the computation. In some cases, this conversion is done by a call to a library routine, which can be expensive compared to using the proper data type that does not require any conversion.

Performance considerations for DISPLAY:  

using 1 to 15 digits (with an odd number of digits) is the fastest

 using 2 to 16 digits (with an even number of digits) is 16% slower than using 1 to 15 digits (with an odd | number of digits)  

using 17 to 18 digits is 60-70% slower than using 1 to 15 digits (with an odd number of digits)

  • PACKED-DECIMAL (COMP-3) : When using PACKED-DECIMAL (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. A call to the library routine is very expensive when compared to doing the calculation in-line. Additionally, using a signed data item with an odd number of digits produces more efficient code since this uses an integral multiple of bytes in storage for the data item.

Performance considerations for PACKED-DECIMAL:  

using an odd number of digits is 5% to 20% faster than using an even number of digits  

using the 16 to 18 digits is up to 140% slower than using 1 to 15 digits

  • Fixed-Point vs Floating-Point : Plan the use of fixed-point and floating-point data types. You can enhance the performance of an application by carefully determining when to use fixed-point and floating-point data. When conversions are necessary, binary (COMP) and packed decimal (COMP-3) data with nine or fewer digits require the least amount of overhead when being converted to or from floating-point (COMP-1 or COMP-2) data. Also, when using fixed-point exponentiations with large exponents, the calculation can be done more efficiently by using operands that force the exponentiation to be evaluated in floating-point.

An example of forcing the exponentiation to be evaluated in floating-point is as follows:
 

 01   A              PIC S9(6)V9(12)         COMP-3 VALUE 0.
 01   B              PIC S9V9(12)             COMP-3 VALUE 1.234567891.
 01   C              PIC S9(10)                 COMP-3 VALUE -99999.


 COMPUTE A = (1 + B) ** C. (original)
 COMPUTE A = (1.0E0 + B) ** C. (forced to floating-point)
 

The above example was forced to floating-point by changing the fixed-point constant value 1 to a floating point constant value 1.0E0.

Performance considerations for fixed-point vs floating-point: forcing an exponentiation to be done in floating-point can be up to 98% faster than doing it in fixed- point

  • Indexes vs Subscripts : Using indexes to address a table is more efficient than using subscripts since the index already contains the displacement from the start of the table and does not have to be calculated at run time. Subscripts, on the other hand, contain an occurrence number that must be converted to a displacement value at run time before it can be used. When using subscripts to address a table, use a binary (COMP) signed data item with eight or fewer digits (for example, using PICTURE S9(8) COMP for the data item). This will allow fullword arithmetic to be used during the calculations. Additionally, in some cases, using four or fewer digits for the data item may also offer some added reduction in CPU time since halfword arithmetic can be used.

Performance considerations for indexes vs subscripts (PIC S9(8)):  

using binary data items (COMP) to address a table is 30% slower than using indexes  

using packed decimal data items (COMP-3) to address a table is 300% slower than using indexes

using DISPLAY data items to address a table is 450% slower than using indexes

  • OCCURS DEPENDING ON : 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. Some performance degradation is expected when using ODO data items since special code must be executed every time a variable-length data item is referenced. This code determines the current size of the item every time the item is referenced. It also determines the location of variably-located data items. Because this special code is outof- line, it may inhibit some optimizations. Furthermore, code to manipulate variable-length data items is substantially less efficient than that for fixed-length data items. For example, 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. If you do use variable-length data items, copying them into fixed-length data items prior to a period of high-frequency use can reduce some of this overhead.

Performance considerations for fixed-length vs variable-length tables:  

using variable-length tables is 5% slower then using a fixed-length table  

using a variable-length table that references the first complex ODO element is 7% slower then using a fixed-length table  

using a variable-length table that references a complex ODO element other than the first is 140% slower then using a fixed-length table


Created with Artisteer

COBOL Program Design.

The appropriate program design is another important factor in determining the performance character-istics of an application. If an inefficient design is used, then you are limited in the amount of performance tuning you can do to the application.
The biggest performance improvement you can make is to use an efficient design. After the design is determined, then you can look at other things such as efficient algo-rithms, data structures and data types, and coding style. Some of these are discussed below.
  • Algorithms : Examine the underlying algorithms that have been selected before looking at the COBOL specifics. Improving the algorithms usually has a much greater impact on the performance than does improving the detailed implementation of the algorithm. As an example, consider two search algorithms: a sequential search and a binary search. Clearly, both of them will produce the same results and may, in fact, have almost the same performance for small tables. However, as the table size increases, the binary search will be much faster than the sequential search. As in this case of the two searches, you may have to do some additional coding to maintain a sorted table for the binary search, but the additional effort spent here is more than saved during the execution of the program.
  • Data Structures and Data Types : After deciding on the algorithm, look at the data structures and data types. Ensure that both are appropriate for the selected algorithm. The algorithm may in general be a fast one, but if the wrong data structures or types are used, the performance can degrade significantly. As an example, consider two PERFORM VARYING loops, one using a USAGE DISPLAY data item for the loop variable and the other using a COMPUTATIONAL data item. In the case of DISPLAY data item, data conversion must be done for each iteration of the loop, whereas in the COMPUTATIONAL data item, binary fullword arithmetic can be used. Once again, they will both produce the same results, but the loop using the COMPUTATIONAL data item will be much faster than the loop using the DISPLAY data item.
Performance considerations for loop control variables (PIC S9(8)): using packed decimal (COMP-3) is 280% slower than using binary (COMP) using DISPLAY is 575% slower than using binary (COMP)
  • Coding Style : Examine the coding style. Ensure that the program is well structured, utilizing the structured coding constructs that are available with IBM Enterprise COBOL. Avoid using the GO TO statement (in particular, the altered GO TO statement) and avoid using PERFORMed procedures that involve irregular control flow (for example, a PERFORMed procedure that cannot reach the end of the procedure). The optimizer can optimize the code better and over larger blocks of code if the programs are well structured and don't have a "spaghetti-like" control flow. Additionally, the programs will be easier to maintain because of the structured logic flow.
  • Factoring Expressions : Factor expressions where possible, especially in loops. The optimizer does not do the factoring for you. For evaluating arithmetic expressions, the compiler is bound by the left-to-right evaluation rules for COBOL. In order for the optimizer to recognize constant computations (that can be done at compile time) or duplicate computations (common subexpressions), move all constants and duplicate expressions to the left end of the expression or group them in parentheses.
  • 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 don't modify it anywhere in the program (if a data item is passed BY REFERENCE to a subprogram, the optimizer considers it to be modified not only at this CALL statement, but also at all CALL statements).
  • Subscript Checking : When using tables, evaluate the need to verify subscripts. Using the SSRANGE option to catch the errors causes the compiler to generate special code at each subscript reference to determine if the subscript is out of bounds. However, if subscripts need to be checked in only a few places in the application to ensure that they are valid, then coding your own checks can improve the performance when compared to using the SSRANGE compiler option.
  • Subscript Usage : Additionally, try to use the tables so that the rightmost subscript varies the most often for references that occur close to each other in the program. The optimizer can then eliminate some of the subscript calculations because of common subexpression optimization. 
Performance considerations for table reference patterns (PIC S9(8)): when referencing tables sequentially, having the leftmost subscript vary the most often can be 50%  slower than having the rightmost subscript vary the most often
  • Searching : When using the SEARCH statement, place the most often used data near the beginning of the table for more efficient sequential searching. For better performance, especially when searching large tables, sort the data in the table and use the SEARCH ALL statement. This results in a binary search on the table.
Performance considerations for search example: using a binary search (SEARCH ALL) to search a 100-element table was 6% faster than using a sequential search (SEARCH) using a binary search (SEARCH ALL) to search a 1000-element table was 83% faster than using a sequential search (SEARCH).

Created with Artisteer

New In-feed ads