Showing posts with label COBOL performance tuning. Show all posts
Showing posts with label COBOL performance tuning. Show all posts

Sunday, 11 August 2013

COBOL ARITH Compiler Option: COMPAT vs EXTEND with Decimal Examples

A COBOL program that adds packed decimal amounts all night can fail or slow down because of a compile option chosen years earlier. The ARITH compiler option controls the maximum number of digits allowed in decimal arithmetic. Most shops run many programs with ARITH(COMPAT), but some finance, billing, and high-volume calculation programs need ARITH(EXTEND).

COBOL ARITH compiler option diagram comparing ARITH COMPAT 18 digits and ARITH EXTEND 31 digits
Choose precision before compile.

What is the COBOL ARITH compiler option?

ARITH tells Enterprise COBOL how much decimal precision the compiler should allow for fixed-point decimal operations. It affects packed decimal, zoned decimal, numeric-edited items, and numeric literals used in arithmetic expressions.

The two common settings are ARITH(COMPAT) and ARITH(EXTEND). The simple rule is this: use COMPAT when 18 decimal digits are enough, and use EXTEND only when the program truly needs decimal results up to 31 digits.

ARITH(COMPAT) vs ARITH(EXTEND)

Option Decimal digit support Typical use
ARITH(COMPAT) Up to 18 digits Standard business calculations where field sizes fit traditional COBOL decimal limits
ARITH(EXTEND) Up to 31 digits Large packed decimal calculations, high-value balances, interest calculations, and migrated code that defines larger decimal fields

When ARITH(COMPAT) is enough

ARITH(COMPAT) is usually enough when the program uses ordinary business fields such as account balances, counts, rates, quantities, and totals that stay within 18 digits. It also keeps behavior closer to older COBOL code, which is why many long-running applications still use it.

01 WS-INVOICE-AMOUNT PIC S9(9)V99 COMP-3.
01 WS-TAX-AMOUNT PIC S9(7)V99 COMP-3.
01 WS-INVOICE-TOTAL PIC S9(10)V99 COMP-3.

These fields do not need 31-digit arithmetic. Changing the program to ARITH(EXTEND) may not add value unless another expression in the program needs the larger intermediate result.

When ARITH(EXTEND) is needed

ARITH(EXTEND) is useful when a calculation can exceed 18 digits before the final result is stored. That can happen when a program multiplies large quantities by rates, rolls up many account balances, or works with long packed decimal fields from a file or Db2 table.

01 WS-LARGE-BALANCE PIC S9(18)V99 COMP-3.
01 WS-INTEREST-RATE PIC S9(3)V9(9) COMP-3.
01 WS-INTEREST-AMOUNT PIC S9(18)V99 COMP-3.
COMPUTE WS-INTEREST-AMOUNT =
WS-LARGE-BALANCE * WS-INTEREST-RATE

Even if the receiving field has a normal size, the intermediate arithmetic can need more room. That is the point where ARITH(EXTEND) deserves a closer look.

Performance tradeoff

The older article stated that ARITH(EXTEND) can be slower than ARITH(COMPAT). That is still a useful warning, but it should not be treated as one fixed percentage for every program. The cost depends on how much decimal arithmetic the program performs, how often the code path runs, and what other work dominates the step.

A batch job that spends most of its time waiting on file I/O may not show much difference. A calculation-heavy program that runs millions of decimal operations in a tight loop may show a measurable CPU change. Measure CPU time and elapsed time before and after changing the compile option.

How to review ARITH safely

1. Find large decimal fields

Search the Data Division for packed decimal, zoned decimal, and edited fields with large picture clauses. Pay special attention to fields near 18 digits and fields used in multiplication, division, or compound COMPUTE statements.

2. Check arithmetic expressions

Look for ADD, SUBTRACT, MULTIPLY, DIVIDE, and COMPUTE. The field receiving the answer is only part of the story. Intermediate results can be larger than the final field.

3. Run representative test data

Use test records that contain maximum expected values, not only happy-path values. A program can pass small test data and still fail month-end or year-end processing when balances are higher.

4. Compare CPU and output

Compile the program with the candidate option, run the same input, compare output files, and check CPU time. Keep the compile listing with the change record so the next developer can see why the option was chosen.

Common mistakes

Using EXTEND everywhere

ARITH(EXTEND) should solve a precision need. Do not apply it to every program just because one calculation failed. Start with the program and expression that need more decimal digits.

Ignoring NUMPROC and TRUNC

ARITH is not the only numeric compile option that matters. Numeric sign handling and binary truncation can also affect results. Review related settings such as COBOL NUMPROC compiler option and COBOL TRUNC compiler option when numeric behavior is under review.

Testing only the final field size

A receiving field can look safe while an intermediate result is not. Review the whole expression, especially multiplication and division statements with large decimal operands.

Quick decision checklist

Question Recommended action
Do all decimal fields and intermediate results stay within 18 digits? Keep ARITH(COMPAT) unless another project standard says otherwise.
Can an expression need 19 to 31 decimal digits? Test with ARITH(EXTEND) and compare output and CPU time.
Is the job calculation-heavy? Measure CPU before and after the change with production-like input volume.
Is the program being migrated to a newer compiler? Check the compiler migration notes and keep compile options documented.

Related Mainframe Forum guides

For nearby compiler settings, read COBOL DATA compiler option, COBOL NUMPROC compiler option, and COBOL TRUNC compiler option. For run-time tuning context, see COBOL performance tuning and COBOL data types.

External references

IBM documents the Enterprise COBOL ARITH compiler option, fixed-point arithmetic, and decimal data.

FAQ

What does ARITH do in COBOL?

ARITH controls the maximum number of decimal digits allowed in fixed-point decimal arithmetic during compilation.

What is the difference between ARITH(COMPAT) and ARITH(EXTEND)?

ARITH(COMPAT) supports up to 18 decimal digits. ARITH(EXTEND) supports up to 31 decimal digits for programs that need larger decimal arithmetic.

Does ARITH(EXTEND) make COBOL slower?

It can add CPU cost in decimal-heavy programs because larger intermediate decimal results may be used. The real effect depends on the program, so test with representative input.

Should every COBOL program use ARITH(EXTEND)?

No. Use ARITH(EXTEND) when the program needs more than 18 decimal digits. For ordinary 18-digit business arithmetic, ARITH(COMPAT) is often enough.

COBOL AWO Compiler Option: APPLY WRITE-ONLY for QSAM Files

A COBOL job that writes variable-length QSAM records can waste output buffer space when every block is cut for the largest possible record. The AWO compiler option applies APPLY WRITE-ONLY behavior to eligible files, so the buffer is written only when the next record will not fit. On the right file shape, that can reduce EXCPs and improve batch run time.

COBOL AWO compiler option diagram showing variable blocked records, AWO, and fewer EXCPs
Use AWO for eligible VB output.

What is the COBOL AWO compiler option?

AWO stands for APPLY WRITE-ONLY. IBM documents that it activates APPLY WRITE-ONLY processing for physical sequential files with variable blocked format. The default is NOAWO.

In practical terms, AWO helps COBOL use output blocks more efficiently for QSAM files that have variable-length blocked records. It is a file-output option, not a general CPU tuning switch for every program.

AWO vs NOAWO

Option Behavior Good fit
NOAWO Does not add implicit APPLY WRITE-ONLY to eligible files. Programs that do not write variable blocked QSAM output, or programs where existing behavior must stay unchanged.
AWO Applies APPLY WRITE-ONLY processing to eligible files. Programs that write blocked variable-length QSAM files, especially when record sizes vary a lot.

How APPLY WRITE-ONLY changes buffering

Without APPLY WRITE-ONLY, the buffer can be written when there is not enough space left for the maximum-size record. With APPLY WRITE-ONLY, the buffer is written only when the next actual record does not fit in the unused part of the buffer.

That difference matters when output records vary in size. If many records are much smaller than the maximum record length, the program can fit more records into each block and issue fewer I/O calls.

Eligible file shape

AWO matters for physical sequential QSAM files with blocked variable-length records. It does not help a fixed-block file in the same way, and it is not meant for VSAM output.

SELECT OUT-FILE ASSIGN TO OUTDD.

FD  OUT-FILE
    RECORDING MODE IS V
    BLOCK CONTAINS 0 RECORDS.
01  OUT-REC.
    05 OUT-ID      PIC X(10).
    05 OUT-TEXT    PIC X(500).

The file must still be defined correctly in JCL. Check RECFM=VB, LRECL, and block-size rules with the storage and operations standards used at your site.

How to specify AWO

The exact place depends on your compile procedure. Some shops set compiler options in cataloged procedures or build tools. For a source-level example, the option can appear in a CBL statement.

CBL AWO

IDENTIFICATION DIVISION.
PROGRAM-ID. WRITVB.

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT OUT-FILE ASSIGN TO OUTDD.

Keep the compile listing or build record with the change. AWO is easy to forget because it changes generated file handling code without changing the visible WRITE statement.

Performance expectation

IBM performance guidance says AWO can save time because fewer calls are made to data management services for input and output handling. IBM also gives examples where programs writing variable-length files ran faster with fewer EXCPs. Treat those examples as proof that the option can matter, not as a promise for every program.

The biggest gains usually come from output files with large variation in record length. If every output record is close to the maximum length, there may be little room to improve block usage.

AWO and BLOCK0

BLOCK0 can make more physical sequential files use system-determined block sizes when the FD does not specify a block size. IBM notes that when BLOCK0 is in effect, AWO might apply to more files because more files may become blocked.

That interaction is useful, but it also means the change deserves testing. A compile-option change can affect more files than the one the developer had in mind.

When to avoid AWO

Avoid treating AWO as a blanket answer for all I/O performance problems. It is useful only for a specific file pattern. Be careful when a job depends on immediate write behavior, custom recovery assumptions, or exact timing of output availability during execution.

If the written record must be forced out as soon as possible, IBM performance guidance recommends avoiding AWO. That is uncommon for ordinary batch output files, but it can matter for special operational files.

Review checklist before changing AWO

  • Confirm the file is physical sequential QSAM output.
  • Confirm the records are variable-length and blocked.
  • Check whether record sizes vary enough to benefit from better buffer use.
  • Review BLOCK0 because it can increase the files where AWO applies.
  • Compare EXCP count, CPU time, and elapsed time before and after the compile change.
  • Keep the compiler listing and JCL evidence with the change record.

Common mistakes

Using AWO on the wrong file type

AWO is not a VSAM tuning option and does not help ordinary fixed-block files in the same way. Start by checking the FD and JCL.

Ignoring the block-size setup

AWO works with blocked variable-length output. If the file is not blocked, review BLOCK CONTAINS, BLOCK0, and the JCL before expecting a result.

Comparing only elapsed time

Elapsed time can move because of system load. Compare EXCPs and CPU time too, especially when the job runs in a busy batch window.

Related Mainframe Forum guides

For nearby topics, read COBOL fixed vs variable-length records, COBOL file organization, COBOL WRITE statement, COBOL BLOCK0 compiler option, and COBOL performance tuning.

External references

IBM documents performance-related compiler options, APPLY WRITE-ONLY buffer behavior, and Enterprise COBOL option comparison.

FAQ

What does AWO do in COBOL?

AWO applies APPLY WRITE-ONLY processing to eligible physical sequential files with variable blocked records.

What is the default for AWO?

IBM documents the default as NOAWO, meaning the compiler does not implicitly apply APPLY WRITE-ONLY to eligible files.

When does AWO help most?

AWO helps most when a program writes blocked variable-length QSAM records and the actual record sizes vary enough to improve buffer use.

Does AWO apply to VSAM files?

No. The AWO compiler option is for eligible physical sequential QSAM files, not VSAM files.

COBOL FASTSRT Compiler Option: When DFSORT Handles Sort I/O

A COBOL program that sorts a million records with SORT ... USING and SORT ... GIVING can spend extra CPU passing control back to COBOL for file input and output. The FASTSRT compiler option changes that path for eligible sorts: DFSORT, or a comparable sort product, performs the input and output instead of Enterprise COBOL.

COBOL FASTSRT compiler option diagram showing COBOL I/O, FASTSRT eligibility, and DFSORT I/O
Let DFSORT handle eligible I/O.

What is the COBOL FASTSRT compiler option?

FASTSRT controls whether the sort product performs input and output for eligible COBOL SORT and MERGE operations. IBM documents the default as NOFASTSRT. With FASTSRT, the sort product can handle files named in USING or GIVING, which avoids returning to COBOL after each record is read or written.

FASTSRT vs NOFASTSRT

Option Who handles sort file I/O? Best fit
NOFASTSRT Enterprise COBOL Sorts that need COBOL file error semantics, file status behavior, or unsupported file handling.
FASTSRT DFSORT or comparable sort product Eligible direct file sorts using USING and/or GIVING, especially high-volume batch sorts.

Simple eligible SORT example

This direct sort is the kind of pattern where FASTSRT can help. The program gives COBOL an input file and an output file, and no custom input or output procedure is needed.

CBL FASTSRT

SELECT INPUT-FILE  ASSIGN TO INFILE.
SELECT SORT-FILE   ASSIGN TO SORTWK.
SELECT OUTPUT-FILE ASSIGN TO OUTFILE.

SD  SORT-FILE.
01  SORT-REC.
    05 SORT-ACCOUNT-NO     PIC X(10).
    05 SORT-DATE           PIC X(8).
    05 SORT-AMOUNT         PIC S9(9)V99 COMP-3.

PROCEDURE DIVISION.
    SORT SORT-FILE
       ON ASCENDING KEY SORT-ACCOUNT-NO
       USING INPUT-FILE
       GIVING OUTPUT-FILE
    GOBACK.

For this shape, the sort product can perform the file I/O when the full list of FASTSRT requirements is met.

When FASTSRT does not help much

FASTSRT does not remove the COBOL logic in an INPUT PROCEDURE or OUTPUT PROCEDURE. If the program must inspect each record, run business rules, and call subprograms before releasing records to the sort, most of the cost may still be in COBOL logic.

SORT SORT-FILE
   ON ASCENDING KEY SORT-ACCOUNT-NO
   INPUT PROCEDURE 2000-BUILD-SORT-RECS
   OUTPUT PROCEDURE 3000-WRITE-REPORT.

Use FASTSRT as a file-I/O improvement for eligible paths, not as a cure for expensive record-level business processing.

Important restrictions

SORTIN and SORTOUT DFSORT options

IBM notes that you cannot use DFSORT SORTIN or SORTOUT options when using FASTSRT. The COBOL USING and GIVING files define the input and output for the statement.

Line-sequential files

FASTSRT does not apply to line-sequential files used as USING or GIVING files. If the program sorts text-style line-sequential data, do not expect this option to change that path.

FILE STATUS behavior

IBM documents that if file status is specified and FASTSRT is used, file status is ignored during the sort. Keep NOFASTSRT when COBOL file error semantics must be preserved for the sort processing.

DCB and sort work files

The compiler can check many FASTSRT eligibility rules, but IBM notes two checks that are not fully verified at compile time: whether sort work files use a device other than direct-access storage, and whether input or output file DCB parameters match the FD. Check the JCL and file definitions before promotion.

How to decide whether to use FASTSRT

  • Use it first on simple SORT ... USING ... GIVING programs.
  • Check whether COBOL file status handling is needed during the sort.
  • Confirm the sort work data sets and DCB information match site standards.
  • Compare CPU time, EXCP counts, elapsed time, and DFSORT messages before and after the change.
  • Keep the compile option visible in the build procedure or compiler listing.

Performance expectation

IBM performance guidance recommends FASTSRT for eligible sorts when COBOL file error handling is not needed. IBM also gives an example where one program processing 100,000 records was faster and used fewer EXCPs with FASTSRT. Treat that as an example, not a fixed promise. Your result depends on record size, sort keys, I/O path, work files, and how much logic remains in COBOL.

Common mistakes

Turning on FASTSRT without checking file status usage

If the program depends on file status during sort I/O, FASTSRT can change the behavior that support teams expect. Review the FD and error handling before changing the compiler option.

Expecting FASTSRT to speed up business logic

FASTSRT targets sort file I/O. It does not make an expensive input procedure cheap if that procedure runs many calls, table scans, or database reads.

Leaving the change undocumented

Record the compiler option change in the build procedure or change record. A future compiler migration is easier when the reason for FASTSRT is visible.

Related Mainframe Forum guides

For related topics, read COBOL SORT procedure, JCL SORT examples, SORT INREC and OUTREC examples, COBOL OPTIMIZE compiler option, and COBOL performance tuning.

External references

IBM documents the Enterprise COBOL FASTSRT compiler option, improving sort performance with FASTSRT, and COBOL 6 performance guidance for FASTSRT.

FAQ

What does FASTSRT do in COBOL?

FASTSRT lets DFSORT or a comparable sort product perform I/O for eligible COBOL sort and merge operations instead of Enterprise COBOL doing that I/O.

What is the default FASTSRT setting?

IBM documents the default as NOFASTSRT, meaning Enterprise COBOL performs the input and output for the sort or merge.

Does FASTSRT work with INPUT PROCEDURE and OUTPUT PROCEDURE?

FASTSRT does not remove the COBOL logic inside input or output procedures. It applies to eligible USING and GIVING file I/O portions.

When should I avoid FASTSRT?

Avoid it when the program needs COBOL file status behavior during sort processing, uses unsupported file types, or cannot meet the FASTSRT requirements.

COBOL RENT Compiler Option: Reentrant Programs on z/OS

A COBOL module used by CICS, IMS preload, or a Db2 stored procedure cannot be treated like a simple one-user batch program. The RENT compiler option tells Enterprise COBOL to generate a reentrant object program, so the same program code can be shared safely while each run gets its own data.

COBOL RENT compiler option diagram showing reentrant code, Language Environment heap storage, and CICS IMS Db2 use cases
Use RENT for reentrant code.

What is the COBOL RENT compiler option?

RENT generates a reentrant object program. NORENT generates a nonreentrant object program. IBM documents RENT as the default for current Enterprise COBOL releases.

Reentrant code is designed so the executable program instructions are not modified during execution. Working data is kept separate for each run unit, task, or invocation as required by the runtime environment.

RENT vs NORENT

Option Generated program Good fit
RENT Reentrant object program. CICS programs, IMS preload, Db2 stored procedures, z/OS UNIX, DLL-enabled programs, object-oriented COBOL, and shared program storage.
NORENT Nonreentrant object program. Older batch-only programs when site rules allow nonreentrant code and storage/addressing rules are understood.

Why reentrant code matters

If more than one user, task, or address space can run the same program at the same time, the program must not overwrite shared instruction storage. IBM states that programs accessed by more than one user at the same time must be made reentrant by compiling with RENT.

This matters in online regions and shared storage. A nonreentrant program can work in a small test, then fail badly when concurrent use starts touching the same program copy.

Programs that should use RENT

IBM lists several Enterprise COBOL cases where programs must be reentrant. The most common mainframe cases are easy to recognize during a code review.

  • CICS application programs.
  • IMS programs that are preloaded.
  • Db2 stored procedures written in COBOL.
  • Programs running in the z/OS UNIX environment.
  • Programs enabled for DLL support.
  • Programs using object-oriented syntax.

WORKING-STORAGE with RENT

One practical change is where program data lives. IBM performance guidance explains that COBOL WORKING-STORAGE is allocated from Language Environment heap storage when the program is compiled with RENT. LOCAL-STORAGE is allocated from Language Environment stack storage.

You do not normally rewrite every variable just because a program uses RENT. But you should understand the storage model when debugging addressability, below-the-line storage pressure, or migration issues.

DATA and RMODE considerations

RENT interacts with DATA and RMODE. IBM notes that DATA(24|31) controls whether dynamic data areas are obtained from below the 16 MB line or from unrestricted storage. IBM also states that programs compiled with NORENT must be RMODE 24, while RENT allows the program to run above the 16 MB line.

CBL RENT,DATA(31)

IDENTIFICATION DIVISION.
PROGRAM-ID. CUSTUPD.

For modern code, DATA(31) with RENT is common, but always follow the runtime environment and site standards.

Binder and link-edit checks

Compiler options and binder attributes need to agree. IBM recommends link-editing the program object with the RENT binder option when all COBOL programs in the program object were compiled with RENT. If non-COBOL programs are included, the binder setting depends on their rules.

If any program in a program object is not reentrant, do not blindly mark the whole program object as reentrant. Check the compile listings and binder map before moving it into shared runtime use.

RENT and performance

Older guidance often says RENT adds some code to support reentrancy. IBM performance material also notes that, on average, RENT was equivalent to NORENT in its measurements. Treat performance as something to measure in the target workload.

For most modern online and shared environments, correctness and environment requirements decide the option before a small path-length discussion does.

Testing RENT safely

Test RENT changes with the same runtime shape the program uses in production. A single batch run proves basic execution, but it does not prove a CICS program, IMS preload module, or Db2 stored procedure behaves correctly under concurrent use.

For a changed program, keep three pieces of evidence: the compiler listing that shows RENT, the binder output that shows the program object attributes, and a run log from the target environment. That small paper trail saves time when a later deployment asks why the option was changed.

Migration checklist

  • Confirm whether the program runs in batch, CICS, IMS, Db2 stored procedure, z/OS UNIX, or DLL mode.
  • Check the actual compiler listing for RENT or NORENT.
  • Review DATA, RMODE, HEAP, STACK, and ALL31 settings with runtime support.
  • Confirm binder attributes in the link-edit output.
  • Check whether the program object contains only COBOL modules or mixed-language modules.
  • Test concurrent execution paths instead of proving only one single-user run.

Common mistakes

Assuming RENT means thread-safe business logic

RENT generates reentrant object code, but it does not make every external resource safe. Files, DB2 rows, queues, shared tables, and application locks still need correct design.

Ignoring the binder map

A compile listing alone does not prove the final program object is packaged correctly. Check the link-edit output, especially when several modules are bound together.

Using old defaults without checking the current compiler

Current Enterprise COBOL documentation lists RENT as the default. Do not rely on memory from an older compiler release; check the listing for the real option.

Related Mainframe Forum guides

For nearby topics, read COBOL DYNAM compiler option, COBOL THREAD compiler option, Working Storage vs Local Storage, COBOL CALL statement examples, COBOL Db2 compilation process, and COBOL performance tuning tips.

External references

IBM documents the RENT compiler option, making programs reentrant, and program residence and storage considerations.

FAQ

What does RENT mean in COBOL?

RENT tells Enterprise COBOL to generate a reentrant object program.

What is the default for RENT?

IBM documents RENT as the default for current Enterprise COBOL releases.

Is RENT required for CICS COBOL programs?

Yes. IBM lists CICS programs among the Enterprise COBOL programs that must be reentrant.

Does RENT make a program thread-safe?

No. RENT handles reentrant object code. Application data, files, queues, database rows, and locking still need proper design.

COBOL SSRANGE Compiler Option: Find Table Bounds Errors

A COBOL table with OCCURS 50 TIMES will not protect itself when a bad subscript tries to read occurrence 51. The SSRANGE compiler option tells Enterprise COBOL to generate runtime checks for table references and reference modification, so these errors are found before they quietly damage nearby storage.

COBOL SSRANGE compiler option diagram showing table OCCURS, range checking, and MSG or ABEND result
Catch bad table references.

What is the COBOL SSRANGE compiler option?

SSRANGE generates code that checks whether subscripts, indexes, ALL subscripts, variable-length references, and reference modification expressions point outside the valid storage area. IBM documents the default as NOSSRANGE.

If SSRANGE is coded without suboptions, IBM treats it as SSRANGE(NOZLEN,ABD). That means zero-length reference modification is treated as an error, and the first detected range problem causes a runtime error and abend.

SSRANGE vs NOSSRANGE

Option Runtime behavior Good fit
NOSSRANGE No generated range-check code for the covered references. Production programs where performance matters and range logic has already been tested.
SSRANGE Generated code checks covered table, index, and reference modification use. Unit test, system test, migration test, and programs with suspected storage overlay.

Table range example

This table allows 50 entries. If WS-SUB becomes 51, the program is trying to address storage outside the table. With SSRANGE, Enterprise COBOL can catch that bad reference at run time.

01 WS-CUSTOMER-TABLE.
   05 WS-CUSTOMER-ENTRY OCCURS 50 TIMES.
      10 WS-CUSTOMER-ID     PIC X(10).
      10 WS-CUSTOMER-BAL    PIC S9(7)V99 COMP-3.

01 WS-SUB                   PIC S9(4) COMP.

MOVE 51 TO WS-SUB
DISPLAY WS-CUSTOMER-ID(WS-SUB)

Without a range check, the display might read some unrelated field after the table. That kind of failure is painful because the abend may happen much later than the bad reference.

Reference modification checks

SSRANGE also checks reference modification for non-UTF-8 data items and function values. IBM documents checks for starting position, current length, ending position, and length value.

01 WS-NAME                  PIC X(20).
01 WS-START                 PIC S9(4) COMP.
01 WS-LEN                   PIC S9(4) COMP.

MOVE 18 TO WS-START
MOVE 5  TO WS-LEN
DISPLAY WS-NAME(WS-START:WS-LEN)

In this example, positions 18 through 22 are requested from a 20-byte field. That should be fixed in logic, not hidden by hoping the next bytes happen to be harmless.

MSG and ABD suboptions

The MSG and ABD suboptions control what happens after a range check fails. Use ABD when the first bad reference should stop the program. Use MSG during migration or wider testing when you want warning messages and continued execution so more range problems can be found in one run.

CBL SSRANGE(MSG)

* or

CBL SSRANGE(ABD)

MSG is useful for discovery, but do not treat a warning-only run as clean production behavior. A bad subscript still needs a code fix.

ZLEN and NOZLEN suboptions

ZLEN and NOZLEN control zero-length reference modification. With ZLEN, a zero length is allowed. With NOZLEN, a zero length gets an SSRANGE error. IBM documents NOZLEN as the compatible behavior with older SSRANGE handling.

CBL SSRANGE(ZLEN,MSG)
CBL SSRANGE(NOZLEN,ABD)

Pick the setting that matches your compiler level and site migration rule. The point is not to make the compile option look tidy; it is to catch the reference rules your application must obey.

Performance impact

SSRANGE adds generated checks to many references. IBM performance guidance recommends NOSSRANGE for best performance and notes that range checking can slow programs that use subscripts, indexes, and reference modification in performance-sensitive paths.

IBM also documents that in COBOL 6 the compiled-in checks are always conducted at run time. You cannot compile with SSRANGE and then turn those checks off later by specifying CHECK(OFF).

When to use SSRANGE

  • Use it during unit test for programs with new or changed tables.
  • Use it when a storage overlay points to bad subscript logic.
  • Use it during compiler migration testing.
  • Use it for a focused diagnostic compile when production data exposes a rare table problem.

When to avoid SSRANGE

Avoid leaving SSRANGE on blindly for call-heavy, table-heavy, or high-volume batch programs unless the site has chosen that tradeoff. If only a few references need checking, a local bounds check around those references can be faster and easier to explain.

IF WS-SUB >= 1 AND WS-SUB <= 50
   DISPLAY WS-CUSTOMER-ID(WS-SUB)
ELSE
   DISPLAY 'BAD CUSTOMER SUBSCRIPT: ' WS-SUB
END-IF

Local checks are also useful when the program should handle bad input gracefully instead of abending on the first bad table reference.

Common mistakes

Thinking SSRANGE checks the subscript value itself

IBM explains that each subscript or index is not individually checked for validity. The effective address is checked to make sure it does not reference outside the table area.

Expecting CHECK(OFF) to disable COBOL 6 SSRANGE checks

For COBOL 6, compiled-in SSRANGE checks remain active at run time. Plan the compile option deliberately.

Using NOSSRANGE to hide a real bug

NOSSRANGE can reduce overhead, but it does not make bad table logic correct. Fix the subscript or reference modification rule first.

Related Mainframe Forum guides

For nearby topics, read COBOL USAGE clause, COBOL ARITH compiler option, COBOL TRUNC compiler option, COBOL fixed vs variable-length records, and COBOL performance tuning.

External references

IBM documents the SSRANGE compiler option, SSRANGE performance guidance, and the related MSG and ABD suboption APAR.

FAQ

What does SSRANGE do in COBOL?

SSRANGE generates runtime checks for out-of-range table references, indexes, subscripts, variable-length references, and reference modification expressions.

What is the default for SSRANGE?

IBM documents the default as NOSSRANGE.

Should SSRANGE be used in production?

Many sites use SSRANGE mainly in test because it adds runtime checks. Production use depends on the program risk, performance cost, and site standards.

Can CHECK(OFF) disable SSRANGE in COBOL 6?

No. IBM documents that COBOL 6 compiled-in SSRANGE checks are always conducted at run time.

COBOL THREAD Compiler Option: When to Use THREAD and NOTHREAD

A normal batch COBOL program does not become faster because it is compiled with THREAD. IBM’s default is NOTHREAD, and that default is right for many ordinary jobs. Use THREAD when the COBOL program must run in a Language Environment enclave that has multiple POSIX threads or PL/I tasks.

COBOL THREAD compiler option diagram showing NOTHREAD default, THREAD for multithreaded execution, and RENT requirement
Use THREAD only when needed.

What is the COBOL THREAD compiler option?

The THREAD compiler option enables an Enterprise COBOL program for execution in a Language Environment enclave with multiple POSIX threads or PL/I tasks. NOTHREAD means the program is not enabled for that kind of threaded execution.

A program compiled with THREAD can still run in a nonthreaded application. The reverse is the risk: if a COBOL program will run in a threaded application, IBM requires all COBOL programs in that Language Environment enclave to be compiled with THREAD.

THREAD vs NOTHREAD

Option Meaning Use it when
NOTHREAD The program is not enabled for multiple POSIX threads or PL/I tasks. The application runs as ordinary batch, CICS, IMS, or single-threaded COBOL.
THREAD The program is enabled for threaded execution in the Language Environment enclave. The application really uses multiple POSIX threads or PL/I tasks and COBOL runs in that environment.

When THREAD is required

Use THREAD when the COBOL program is part of an application that runs COBOL on more than one thread inside the same Language Environment enclave. This is not the usual shape of old batch programs. It is more likely in mixed-language applications, z/OS UNIX work, or PL/I tasking cases where COBOL is called inside threaded execution.

IBM also states that object-oriented COBOL clients and classes should use THREAD. For normal procedural programs, do not make the change unless the runtime environment needs it.

Required companion settings

RENT is required

Threaded COBOL programs must be compiled with RENT, and the load module must be linked with the binder RENT option. RENT means the program is built for reentrant execution, which matters when more than one thread can use the same program code.

PROGRAM-ID must be recursive

Before compiling with THREAD, code the RECURSIVE phrase in the PROGRAM-ID paragraph. IBM documents this as a requirement for threaded COBOL programs.

IDENTIFICATION DIVISION.
PROGRAM-ID. PAYCALC RECURSIVE.
PROCEDURE DIVISION USING LK-PAY-INPUT LK-PAY-OUTPUT.
GOBACK.

How to specify THREAD

The exact compile JCL depends on your site procedure, but the option often appears in a compiler parameter or source-level compiler directive.

//COBOL.SYSIN DD *
CBL THREAD,RENT
IDENTIFICATION DIVISION.
PROGRAM-ID. PAYCALC RECURSIVE.
...
/*

If your build uses Endevor, Changeman, DBB, zAppBuild, or another pipeline, record the compiler options in the build configuration instead of relying on a comment in the source.

Performance impact

THREAD can add runtime cost because the compiler and runtime must protect shared execution paths with serialization logic. IBM notes that I/O verbs such as OPEN, READ, WRITE, REWRITE, and CLOSE are protected by locks when THREAD is used.

The older version of this article mentioned CALL overhead tests where THREAD was slower. Keep that as a warning, not as a universal number. Measure the actual job or service path before rolling the option across a group of programs.

Language restrictions with THREAD

Some older COBOL language elements are not supported when THREAD is in effect. IBM lists restrictions such as ALTER, nested programs, SORT or MERGE statements, RERUN, USE FOR DEBUGGING, and the INITIAL phrase or INITIAL compiler option.

If the source has older control-flow patterns or internal sort logic, compile testing may expose errors after THREAD is added. Review those constructs before the change is sent into a shared build stream.

CICS and IMS note

IBM says a program compiled with THREAD can run in CICS or IMS as long as the application does not contain multiple POSIX threads or PL/I tasks at runtime. That does not mean CICS itself becomes a threaded COBOL application. For CICS programs, follow the site’s CICS compile procedure and avoid changing THREAD just because the program is online.

Review checklist before changing to THREAD

  • Confirm the application really runs COBOL on multiple POSIX threads or PL/I tasks.
  • Compile all COBOL programs in the Language Environment enclave with THREAD.
  • Compile with RENT and link-edit with binder RENT.
  • Add RECURSIVE to the outermost PROGRAM-ID.
  • Remove unsupported constructs before the compile is promoted.
  • Run CPU and elapsed-time comparison tests with production-like volume.

Common mistakes

Using THREAD for ordinary batch

Most batch jobs do not need THREAD. If the job is single-threaded, NOTHREAD avoids unnecessary serialization cost.

Compiling only one program with THREAD

For a true threaded COBOL application, all COBOL programs in the Language Environment enclave must use THREAD. A partial change can leave the run unit in an unsupported or fragile state.

Forgetting recursive program rules

THREAD and recursive behavior go together. Add RECURSIVE, review Working-Storage usage, and keep shared state under control.

Related Mainframe Forum guides

For nearby compiler-option topics, read COBOL RENT compiler option, COBOL DATA compiler option, COBOL DYNAM compiler option, COBOL TEST compiler option, and COBOL CALL statement.

External references

IBM documents the Enterprise COBOL THREAD compiler option, choosing THREAD support, and COBOL multithreading limitations.

FAQ

What is the default for the COBOL THREAD option?

The Enterprise COBOL default is NOTHREAD. Use THREAD only when the application needs threaded COBOL execution.

Does THREAD improve COBOL performance?

No. THREAD can add overhead because serialization logic is generated for threaded execution. Use it for correctness in threaded applications, not as a tuning switch.

Does THREAD require RENT?

Yes. IBM states that threaded COBOL programs must be compiled with RENT and linked with the binder RENT option.

Can THREAD programs run in CICS or IMS?

IBM says a program compiled with THREAD can run in CICS or IMS when the application does not contain multiple POSIX threads or PL/I tasks at runtime.

New In-feed ads