Showing posts with label COBOL compiler options. Show all posts
Showing posts with label COBOL compiler options. Show all posts

Sunday, 11 August 2013

COBOL Performance Tuning: Compiler Options and Runtime Tips

A COBOL batch job that runs for four hours rarely has one magic fix. The slow part may be a table search inside a million-record loop, a small QSAM block size, a SORT returning control record by record, decimal data that needs extra sign handling, or a production compile still using development options. Good COBOL performance tuning starts with evidence from the job log, SMF data, Application Performance Analyzer, RMF, or the site tool your shop uses.

COBOL performance tuning diagram showing measurement, compiler options, file I/O, and FASTSRT
Measure before changing options.

What is COBOL performance tuning?

COBOL performance tuning means reducing CPU time, elapsed time, I/O waits, storage pressure, or chargeable cost without changing the business result. On z/OS, that usually means checking the program logic, compile options, Language Environment settings, file handling, DB2 or VSAM access, and SORT usage together.

The compile listing is the first low-effort check. It shows the actual compiler options used at your site, including any installation defaults that were applied even when the JCL did not specify them.

Start with measurement

Do not tune a job from memory or from a copied option list. Capture the current behavior first. A small change that reduces CPU but increases elapsed time may still be a bad trade in a nightly batch window.

Signal What it tells you Where to look
CPU time Program instruction cost. Job log, SMF, performance tool.
Elapsed time Wall-clock batch window impact. Scheduler history, job output, SMF.
EXCP or I/O count Dataset access cost. SMF, job accounting, monitor reports.
DB2 calls SQL access path and fetch volume. DB2 accounting, EXPLAIN, package stats.
Abends or bad data Options may be hiding data issues. SYSUDUMP, CEEDUMP, application logs.

Compiler options that affect runtime

IBM lists several Enterprise COBOL compiler options that can affect runtime behavior. The right setting depends on the compiler level, processor level, program data, and whether the compile is for test or production.

OPT, ARCH, and TUNE

IBM recommends OPT(2), ARCH(x), and TUNE(y) for best Enterprise COBOL 6 performance. Choose ARCH for the oldest processor where the program may run, including disaster recovery. Choose TUNE for the processor where it usually runs. TUNE must be equal to or higher than ARCH.

//COBOL.SYSIN DD *
       CBL OPT(2),ARCH(12),TUNE(12)
       IDENTIFICATION DIVISION.
       PROGRAM-ID. PAYTUNE.
       ...
/*

Do not copy the sample values blindly. A module compiled for a higher ARCH level can fail if it is moved to an older machine.

TEST and SSRANGE

TEST and SSRANGE are useful during testing and debugging. They can also add overhead. For production, many shops move to NOTEST or a lower-impact debug setting, and NOSSRANGE after bounds issues have been tested. Keep the site standard and audit requirements in mind.

NUMPROC, TRUNC, and ARITH

Numeric options can affect both speed and correctness. NUMPROC(PFD) can reduce extra sign-fix processing, but only when packed and display numeric data contains preferred signs. TRUNC(OPT) can avoid extra binary truncation code, but it assumes data follows the declared picture and usage. ARITH(EXTEND) allows larger intermediate decimal results and can cost more CPU for decimal-heavy programs.

DYNAM, RENT, and THREAD

DYNAM can make maintenance easier because called subprograms can be replaced without relinking the main load module. It can add call overhead. RENT and THREAD may be needed for the runtime environment, but do not treat them as free speed settings. Use them because the program and environment need them.

File I/O tuning

Many COBOL batch jobs spend more time waiting on data than calculating. For QSAM files, check block size, record format, buffering, and whether the file is read in the best sequence. IBM notes that AWO can reduce calls to data management services for QSAM variable-mode output files, and BLOCK0 can let the system determine block size for eligible QSAM output files.

Check these file items

  • Use sensible block sizes instead of forcing tiny blocks.
  • Read the file in key or physical sequence when the job allows it.
  • Avoid opening and closing the same file repeatedly inside a loop.
  • Use the file status field so failed I/O does not trigger wasteful retry paths.
  • For VSAM, check whether the access pattern matches KSDS, ESDS, RRDS, or LDS usage.

SORT and FASTSRT

If a COBOL program uses the SORT statement, check whether FASTSRT applies. IBM describes FASTSRT as a way for DFSORT or an equivalent product to handle input and output without returning to COBOL after each record. Not every sort is eligible, so verify the compile listing and SORT messages.

       SORT SORT-FILE
            ON ASCENDING KEY SORT-ACCOUNT
            USING INPUT-FILE
            GIVING OUTPUT-FILE.

When the SORT step is the bottleneck, also review SORT work space, input order, record length, and whether the sort belongs inside COBOL or as a separate JCL SORT step.

Code patterns that often cost CPU

Compile options help, but source code still matters. A clean compile cannot save a program that searches a 50,000-row table for every input record when a sorted table, binary search, or indexed lookup would fit the problem better.

Look for these patterns

  • Linear table searches inside high-volume loops.
  • Repeated date or string conversion for the same value.
  • Moving large group items when only one elementary field is needed.
  • Calling a small subprogram millions of times when inline logic would be safer and faster.
  • Repeated SQL singleton SELECTs where one cursor fetch can reduce DB2 calls.

A practical tuning checklist

  1. Capture current CPU, elapsed time, I/O count, and major waits.
  2. Read the compile listing and record the actual compiler options.
  3. Check whether production modules are still compiled with debug-heavy settings.
  4. Review hot loops, table searches, calls, file reads, and SQL calls.
  5. Change one major item at a time and rerun the same workload.
  6. Keep a note of the old value, new value, test data, and measured result.

Safe production approach

Tuning should go through the same control path as any other production change. Recompile with the chosen options, compare output files, compare return codes, check numeric totals, and keep the old load module available for rollback. For money fields and packed decimals, include bad-data tests before changing NUMPROC, TRUNC, or ARITH.

Related COBOL tuning topics

For specific compiler option notes, read COBOL OPTIMIZE Compiler Option, COBOL ARITH Compiler Option, COBOL FASTSRT Compiler Option, COBOL AWO Compiler Option, COBOL SSRANGE Compiler Option, COBOL TEST Compiler Option, and COBOL NUMPROC Compiler Option.

External references

Technical notes in this refresh were checked against IBM guidance for tuning COBOL 6 compiler options, IBM performance-related compiler options, and IBM Enterprise COBOL compiler options.

FAQ

Which COBOL compiler options usually affect performance?

Common options include OPT, ARCH, TUNE, FASTSRT, AWO, NUMPROC, TRUNC, ARITH, SSRANGE, TEST, DYNAM, and THREAD.

Should production COBOL always use OPT(2)?

IBM recommends OPT(2) for best Enterprise COBOL 6 performance, but production settings must match your shop standard, debug needs, data quality, and processor compatibility.

Can compiler options fix slow SQL?

No. If the main cost is DB2 access, review SQL predicates, indexes, EXPLAIN output, fetch count, and commit pattern. COBOL compile options will not fix a bad access path.

When should I use FASTSRT?

Use FASTSRT when the COBOL SORT is eligible and the site SORT product can handle the input and output path more efficiently than record-by-record COBOL control.

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 DATA Compiler Option: DATA(24), DATA(31), and 16 MB Storage

A COBOL batch program can run out of below-the-line storage long before the machine is short of memory. The DATA compiler option helps decide where some run-time data areas can be allocated: below the 16 MB line with DATA(24), or above it with DATA(31).
COBOL DATA compiler option showing DATA 24 and DATA 31 storage placement
DATA(31) is the normal choice for modern programs.

This article explains the DATA compiler option in simple terms for mainframe COBOL developers. It covers what DATA(24) and DATA(31) mean, when each setting is used, and what to check before changing an old compile option.

What the COBOL DATA Compiler Option Controls

The DATA option affects where storage is obtained for dynamic data areas in Enterprise COBOL for z/OS. IBM documents DATA(31) as the default. For reentrant programs, DATA works with the Language Environment HEAP run-time option to decide whether dynamic areas such as non-external WORKING-STORAGE and FD record areas can be placed above the 16 MB line.

The important point is addressability. A program using 31-bit addressing can address storage above the 16 MB line. An old AMODE 24 program cannot. That is why DATA(24) still appears in some old compile procedures.

DATA(31) in COBOL

DATA(31) allows eligible dynamic run-time storage to be allocated above the 16 MB line. IBM recommends DATA(31) when the program does not need to call and pass parameters to AMODE 24 subprograms. In practice, this is the normal setting for most current Enterprise COBOL applications.

Why DATA(31) Helps

Below-the-line storage is limited. If QSAM buffers, working areas, and record areas all compete for that space, a busy batch job can hit storage pressure. With DATA(31), a reentrant program can keep more eligible storage above the line, especially when the run uses HEAP(,,ANYWHERE).

//COBOL.SYSIN DD *
PROCESS RENT,DATA(31)
IDENTIFICATION DIVISION.
PROGRAM-ID. ACCTLOAD.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-ACCOUNT-AREA PIC X(4096).
/*

This does not automatically make a slow program fast. The main benefit is storage placement. It can reduce pressure below the 16 MB line when the program and run-time options are set up correctly.

DATA(24) in COBOL

DATA(24) places eligible dynamic areas below the 16 MB line. You normally use it when the COBOL program must pass data to a 24-bit subprogram that cannot address data above the line.

Typical DATA(24) Scenario

Suppose a new COBOL program calls an old assembler routine that is linked AMODE 24. If the COBOL program passes the address of a work area above the 16 MB line, the old routine may not be able to address it. In that case, the compile and link-edit settings need a careful compatibility review before the program is promoted.

       CALL "OLDASM24" USING WS-CONTROL-BLOCK.

If OLDASM24 can only use 24-bit addresses, the storage passed in WS-CONTROL-BLOCK must be reachable by that routine. That is the kind of case where DATA(24) can still be required.

DATA(24) vs DATA(31)

Setting What it means When to use it
DATA(31) Eligible dynamic storage can be obtained above the 16 MB line. Use for most modern Enterprise COBOL programs unless an AMODE 24 dependency requires below-the-line data.
DATA(24) Eligible dynamic storage is kept below the 16 MB line. Use when the program passes data to AMODE 24 code that cannot address above-the-line storage.

What DATA Does Not Control

DATA is easy to misunderstand because the name sounds broad. It does not control every COBOL data item in every situation. IBM notes that LOCAL-STORAGE is not affected by the DATA compiler option; the stack run-time option and program addressing mode matter there instead.

External data also has related addressability rules. If a program uses EXTERNAL items, old called modules, or mixed-language calls, review the compile options, link-edit attributes, and Language Environment run-time options together.

How DATA Works with RENT and HEAP

The DATA option is often discussed with RENT because reentrant programs can have different storage behavior from non-reentrant programs. IBM notes that for non-reentrant programs, the RMODE option determines where non-external data is allocated.

For a reentrant program, this combination is common in modern compile procedures:

PROCESS RENT,DATA(31)

At run time, HEAP(,,ANYWHERE) can allow non-external WORKING-STORAGE and non-external FD record areas to be allocated above the 16 MB line. This is useful for batch programs with many files, large record areas, or sizable work areas.

How to Check the DATA Option in a Compile Listing

The fastest way to confirm the active setting is to check the compiler listing. Enterprise COBOL listings show the compiler options used for the compile. Site defaults can also affect the final option set, so do not rely only on what appears in the source member.

PROCESS RENT,DATA(31),MAP,XREF

If the source does not specify DATA, check the compile JCL, cataloged procedure, compiler option file, and installation defaults. Many shops keep options in a compile PROC rather than in each COBOL source member.

Migration Checks Before Changing DATA

Changing DATA(24) to DATA(31) is usually a good cleanup target, but it should not be done blindly. Check the called modules first. The risky case is not a normal COBOL-to-COBOL call in a current environment; the risky case is old code that still expects below-the-line addresses.

Before Changing DATA(24) to DATA(31)

  • Check whether the program calls assembler, old COBOL, PL/I, C, or vendor modules.
  • Check the AMODE and RMODE of the load modules involved in the run unit.
  • Review parameters passed through CALL ... USING.
  • Run a compile listing with MAP if you need storage layout detail.
  • Test the largest realistic input, not only a tiny unit-test file.

Common Mistakes

Using DATA(24) Forever Because It Was Already There

Old compile options often survive because nobody wants to touch them. If the program has no AMODE 24 dependency, DATA(31) is usually the better setting because it can reduce pressure below the line.

Expecting DATA(31) to Fix CPU Time

DATA(31) is about storage addressability, not SQL access paths or loop design. For CPU and elapsed-time issues, check the related Mainframe Forum notes on COBOL performance tuning and COBOL performance.

Ignoring LOCAL-STORAGE

If the issue involves LOCAL-STORAGE, the DATA option may not be the setting you need to review. Read the related guide on COBOL Working Storage vs Local Storage.

Related COBOL Compiler Options

The DATA option is only one part of a compile standard. When tuning or modernizing COBOL compile procedures, also review COBOL RENT compiler option, COBOL TRUNC compiler option, COBOL NUMPROC compiler option, and COBOL program compilation process.

FAQ

What is the default DATA option in Enterprise COBOL?

IBM documents DATA(31) as the default for Enterprise COBOL. Site installation defaults can still matter, so check the compile listing for the option actually used.

When should I use DATA(24)?

Use DATA(24) when a program running in 31-bit mode must pass data to AMODE 24 code that cannot address storage above the 16 MB line.

Does DATA affect LOCAL-STORAGE?

No. IBM documents that LOCAL-STORAGE is not affected by the DATA compiler option. Stack settings and program addressing mode control that area.

Does DATA(31) improve COBOL performance?

Not directly. It can reduce below-the-line storage pressure, but it is not a CPU tuning switch. Treat it as a storage addressability option.

References

For exact syntax and current compiler behavior, use IBM documentation for the DATA compiler option, DATA(24) and DATA(31), and Enterprise COBOL compiler options.

Use DATA(31) by default for current programs, and keep DATA(24) only when a real below-the-line dependency proves it is needed.

COBOL NUMPROC Compiler Option: PFD, NOPFD, and MIG Migration

A payroll program can compare two packed decimal fields correctly for years, then fail after one upstream file starts sending a non-preferred sign nibble. The NUMPROC compiler option tells Enterprise COBOL how much checking or correction it should do for signs in packed decimal and DISPLAY numeric data.

COBOL NUMPROC compiler option diagram comparing PFD, NOPFD, and MIG sign handling
Check numeric signs.

What is the COBOL NUMPROC compiler option?

NUMPROC controls how Enterprise COBOL treats numeric signs when it generates code for arithmetic, comparisons, and moves involving packed decimal and DISPLAY numeric items. It matters most when old files, hand-built test data, assembler routines, or converted applications can contain signs that do not match the preferred COBOL format.

The settings you will usually discuss are NUMPROC(PFD), NUMPROC(NOPFD), and older NUMPROC(MIG) migration behavior. For Enterprise COBOL 6, IBM documents that NUMPROC(MIG) is not supported the way it was in older compilers. The option is not a general performance switch. It is a data assumption. Pick it based on whether your input data always uses preferred signs.

NUMPROC(PFD), NOPFD, and MIG at a glance

Option Assumption Best fit
NUMPROC(PFD) Numeric data has preferred signs. Clean COBOL-created data where signs have already been verified.
NUMPROC(NOPFD) Signs may need generated code to handle non-preferred forms. Mixed-source data, old feeds, or files touched by non-COBOL programs.
NUMPROC(MIG) Legacy migration behavior from older compiler levels. Old compile decks and migration reviews; not a normal Enterprise COBOL 6 target setting.

What preferred signs mean

A signed packed decimal field stores the sign in the last half-byte. COBOL programs normally write preferred signs, but real production data does not always stay that neat. A file might be produced by assembler, copied from a different platform, repaired manually, or loaded by a utility that did not validate every numeric sign.

01 WS-GROSS-PAY     PIC S9(7)V99 COMP-3.
01 WS-DEDUCTION     PIC S9(7)V99 COMP-3.
01 WS-NET-PAY       PIC S9(7)V99 COMP-3.

If every value in those fields has a valid preferred sign, NUMPROC(PFD) lets the compiler generate shorter paths for many numeric operations. If the signs are not trustworthy, PFD can let bad data pass into comparisons or arithmetic without the extra generated handling you expected.

When NUMPROC(PFD) is a good choice

Use NUMPROC(PFD) when the program owns the data or every input feed has been checked. For example, a payroll calculation program that reads a VSAM file written only by COBOL programs, validates signed fields on input, and rejects bad records can often use PFD.

Do not choose PFD just because it may reduce CPU time. The option is safe only when the numeric data promise is true. One bad sign in a high-value record can be more expensive than a small CPU saving.

When NUMPROC(NOPFD) is safer

NUMPROC(NOPFD) is safer when signed numeric fields arrive from several sources. Common examples include old conversion files, test records copied from production, records updated by assembler, and feeds from distributed systems that were transformed before reaching z/OS.

IF CUSTOMER-BALANCE < ZERO
   PERFORM WRITE-CREDIT-REVIEW
END-IF

That comparison looks simple, but the compiler option decides how much sign handling is generated. If the file has suspect signs, keep the safer setting while you identify the source and clean the data.

Where NUMPROC(MIG) fits

NUMPROC(MIG) is mainly a legacy migration topic. If you find it in an old compile deck, treat that as a sign that the program needs migration review. IBM documents that Enterprise COBOL 6 does not support NUMPROC(MIG); if it is specified, the compiler issues a warning and uses the default NUMPROC setting.

A good migration plan compares compile listings, regression-test results, and records rejected by numeric checking. When the data is clean and test evidence is strong, move the program to the site standard option such as NUMPROC(NOPFD) or NUMPROC(PFD).

Use NUMCHECK during migration

For Enterprise COBOL migration work, NUMCHECK can help find invalid numeric data at run time. It is especially useful when a team wants to prove whether NUMPROC(PFD) is safe for a program. Use it in test or controlled verification runs, then review the records and code paths it reports.

//COBOL.SYSIN DD *
       PROCESS NUMPROC(NOPFD),NUMCHECK
/*

The exact compile syntax and suboptions depend on your compiler level and site defaults. Always check the compiler listing because the listing is the evidence of what the compiler actually used.

Safe review checklist

  • Find signed COMP-3 and DISPLAY numeric fields in the Data Division.
  • List every external file, Db2 extract, MQ message, and copybook feeding those fields.
  • Check whether non-COBOL programs can create or change the data.
  • Run representative test files with numeric checking before moving to NUMPROC(PFD).
  • Compare results for arithmetic, comparisons, and moves after the compile option change.
  • Record the final compiler option in the build standard, not only in one compile job.

Common mistakes

Using PFD because it sounds faster

PFD can generate more efficient code in some cases, but it is safe only when the data has preferred signs. The right question is not "Which option is faster?" The right question is "Can every signed numeric input be trusted?"

Leaving MIG forever

MIG is useful during migration, but a long-term compiler standard should be clear. If a program still needs migration behavior years later, document the reason and the data source that prevents cleanup.

Testing only clean data

A short unit test with perfect values does not prove the production file is safe. Include old records, rejected records, boundary amounts, negative balances, and records created by non-COBOL writers.

Related Mainframe Forum guides

For connected COBOL topics, read COBOL USAGE Clause, COBOL COMP-3 Packed Decimal, COBOL COMPUTE Statement, COBOL ARITH Compiler Option, COBOL OPTIMIZE Compiler Option, and COBOL Data Types.

External references

IBM documents the option in Enterprise COBOL NUMPROC, tuning guidance in NUMPROC migration and performance guidance, numeric checking in Enterprise COBOL NUMCHECK, and removed option behavior in compiler options not available in Enterprise COBOL.

FAQ

What does NUMPROC(PFD) mean in COBOL?

NUMPROC(PFD) tells the compiler to assume signed numeric data uses preferred signs. Use it only when input data has been verified.

Is NUMPROC(PFD) always faster?

No. It can reduce generated sign-handling code in some programs, but the visible performance effect depends on the workload. Correct numeric results come first.

When should I use NUMPROC(NOPFD)?

Use NOPFD when signed numeric data can come from old files, non-COBOL writers, conversions, or any source where signs may not be preferred.

Is NUMPROC(MIG) a permanent setting?

It is a legacy migration setting. In Enterprise COBOL 6, IBM documents that it is not supported and the compiler uses the default NUMPROC setting after a warning.

COBOL OPTIMIZE Compiler Option: OPT(0), OPT(1), OPT(2)

OPT(2) tells IBM Enterprise COBOL to apply its highest documented optimization level to the generated object program. That setting can improve runtime performance, but it also assumes that the source, input data, and related compiler-option contracts are valid.

COBOL OPTIMIZE compiler option levels OPT 0 OPT 1 and OPT 2
Choose the optimization level for the build stage, then verify the option in the compiler listing.

What does the COBOL OPTIMIZE compiler option do?

The COBOL OPTIMIZE compiler option controls how much work the compiler performs to reduce the runtime or storage cost of generated code. Current Enterprise COBOL syntax is OPTIMIZE(0), OPTIMIZE(1), or OPTIMIZE(2), abbreviated as OPT(0), OPT(1), and OPT(2).

This page focuses only on OPTIMIZE. For a wider option set, see COBOL compiler and runtime performance tips and the broader COBOL performance tuning checklist.

OPT(0), OPT(1), and OPT(2) compared

LevelCompiler behaviorTypical useDebug effect with TEST
OPT(0)Limited optimization and shortest compile timeInitial code changes, diagnosis, and unit testingFull debug capabilities
OPT(1)Runtime-oriented transformations, basic inlining, local simplification, and value propagationA measured middle level when build or debugging constraints matterMost debug capabilities
OPT(2)More aggressive simplification, instruction scheduling, and interblock optimizationRegression-tested production buildsSome debug capabilities
Product default versus site default: IBM documents OPT(0) as the product default. Your installation can change or fix defaults, so use the compiler listing—not an assumption—to confirm the option that built a program.

What OPT(1) can change

At OPT(1), the compiler can simplify control flow, reduce repeated computations, evaluate constant expressions during compilation, combine suitable contiguous moves, rearrange blocks, and remove unreachable code. When INLINE is also active, the compiler can consider inlining eligible PERFORM procedures.

Source code and generated instructions no longer have a simple one-to-one relationship. A debugger can still provide most capabilities with TEST at this level, but the execution path can reflect moved, combined, or removed work.

What OPT(2) adds

OPT(2) applies the OPT(1) work and adds more aggressive simplification and instruction scheduling. IBM also identifies interblock transformations such as global value propagation and loop-invariant code motion. IBM recommends OPT(2) as part of the best-performance option set for Enterprise COBOL 6.

That recommendation is a build target, not proof that every program will improve by a particular percentage. Measure the program with the same input volume and comparable system conditions before and after recompilation.

Legacy STD and FULL syntax mapping

The original post described OPTIMIZE(STD) and OPTIMIZE(FULL). Since Enterprise COBOL 5, IBM removed those forms but tolerates them for compatibility and maps them as follows:

Legacy optionCurrent mapping
NOOPTIMIZEOPTIMIZE(0)
OPTIMIZEOPTIMIZE(2)
OPTIMIZE(STD)OPTIMIZE(2)
OPTIMIZE(FULL)OPTIMIZE(2) plus STGOPT

Use the numbered form in maintained build standards. It states the intended level directly and avoids carrying old terminology into new compiler migrations.

How to specify OPTIMIZE in source

A PROCESS or CBL statement can specify most compiler options. It must appear before the IDENTIFICATION DIVISION header and before comment lines or other compiler-directing statements.

CBL OPT(2),ARCH(13),TUNE(13)
IDENTIFICATION DIVISION.
PROGRAM-ID. PAYCALC.

Do not copy the architecture values blindly. Select ARCH for the oldest processor on which the module can run, including disaster-recovery machines. Select TUNE for the processor used most often, and keep TUNE greater than or equal to ARCH.

How to specify OPTIMIZE in compile JCL

Compiler options can also be passed on the compiler invocation. The exact cataloged procedure varies by installation, but a direct compiler step can use a PARM string such as:

//COBOL    EXEC PGM=IGYCRCTL,REGION=0M,
//         PARM='OPT(2),ARCH(13),TUNE(13)'

If your site uses a compile procedure, place the option on the documented procedure symbol instead of assuming its parameter name. Review the listing to confirm the final resolved settings.

Compiler-option precedence under z/OS

For options that are not fixed, IBM documents this high-to-low precedence:

  1. Fixed installation defaults, which an application build cannot override.
  2. Certain batch-wide settings in effect for the first program.
  3. PROCESS or CBL statements in the source program.
  4. Compiler invocation options, including the JCL PARM value.
  5. Nonfixed installation defaults.

If JCL requests OPT(2) but a source CBL statement requests OPT(0), the source setting normally wins unless the installation fixed the option. This is why the compiler listing belongs with the promoted load module.

OPTIMIZE and TEST debugging behavior

IBM documents full debug capabilities with TEST at OPT(0), most at OPT(1), and some at OPT(2). Higher optimization can move, combine, inline, or remove generated work, so a source statement might not correspond to a single executable instruction range.

Use the COBOL TEST compiler option guide for debug-build choices. For targeted condition-handler visibility, IBM prefers the VOLATILE clause over reducing optimization for an entire program where VOLATILE fits the design.

Use a two-step migration build

IBM recommends a two-step compile process when moving or changing Enterprise COBOL programs. A diagnostic build can use runtime checks and OPT(0):

OPT(0),SSRANGE,NUMCHECK,PARMCHECK,INITCHECK

After invalid-data and storage-reference problems are corrected, the QA and production candidate can remove the runtime checks and use:

OPT(2),NOSSRANGE,NONUMCHECK,NOPARMCHECK

Follow local standards and preserve a repeatable test record. The SSRANGE guide, NUMPROC guide, and ARITH guide explain related data and arithmetic choices.

Valid data matters more at higher optimization

The optimizer assumes the program and data comply with the selected compiler options. Invalid packed-decimal signs, invalid zoned-decimal digits, out-of-range subscripts, storage overlays, or a call-interface mismatch can appear to behave differently after an optimization-level or compiler-version change.

Do not diagnose an OPT(2) difference as a compiler fault first: reproduce it with diagnostic options, verify input data and call interfaces, and correct undefined application behavior before comparing generated code.

OPT(2), ARCH, and TUNE work together

IBM's best-performance set for Enterprise COBOL 6 is OPT(2), ARCH(x), and TUNE(y). OPT controls transformation depth. ARCH controls which processor instructions the generated module may use. TUNE guides instruction selection and scheduling for the processor used most often.

A build that selects an ARCH level newer than a disaster-recovery processor can produce a module that cannot run there. Record both production and recovery hardware requirements in the compiler-option standard.

When MAXPCF can reduce optimization

Enterprise COBOL calculates a program complexity factor for optimization control. If that value exceeds a nonzero MAXPCF threshold, a requested OPT(1) or OPT(2) can be reset to OPT(0) and the compiler issues a warning.

Do not assume that a requested option was applied to a very large program. Check the listing for the effective option, the complexity warning, compile return code, and available region or MEMLIMIT before changing MAXPCF.

Measure an OPT(2) rollout

  1. Capture the compiler version, all effective options, binder settings, and load-module identity.
  2. Run the old and new modules with the same representative input and output checks.
  3. Compare CPU time or service units, elapsed time, EXCP or I/O behavior, and storage only where the measurement source is reliable.
  4. Repeat enough runs to separate a code change from workload and system noise.
  5. Promote only after functional results match and rollback material is retained.

Compiler optimization cannot repair an inefficient SQL access path or excessive file I/O. The COBOL runtime performance-options guide covers other build and execution factors.

COBOL OPTIMIZE rollout checklist

  • Replace tolerated STD/FULL syntax with an explicit numbered level in maintained standards.
  • Confirm the effective setting in the compiler listing.
  • Run diagnostic checks before moving a migrated application to OPT(2).
  • Verify ARCH against every processor that might execute the program.
  • Keep TUNE greater than or equal to ARCH.
  • Investigate MAXPCF warnings and compiler storage failures.
  • Compare functional output before evaluating runtime measurements.

Official IBM references

COBOL OPTIMIZE FAQ

What is the default COBOL OPTIMIZE level?

IBM Enterprise COBOL documents OPTIMIZE(0) as the product default, but a site can change or fix installation defaults. Check the compiler listing to see the option actually in effect.

What is the difference between OPT(1) and OPT(2)?

OPT(1) applies runtime-oriented transformations such as basic inlining and local simplification. OPT(2) adds more aggressive simplification, instruction scheduling, and interblock work such as global value propagation and loop-invariant code motion.

What happened to OPTIMIZE(STD) and OPTIMIZE(FULL)?

Since Enterprise COBOL 5, those forms are removed but tolerated for compatibility. IBM maps OPTIMIZE(STD) to OPTIMIZE(2) and OPTIMIZE(FULL) to OPTIMIZE(2) with STGOPT.

Should every production program use OPT(2)?

IBM recommends OPT(2) for best performance, but each application still needs functional regression testing, valid-data checks, compatible ARCH and TUNE values, and before-and-after runtime measurement under representative workloads.

The compiler listing is the final authority for a build: it shows whether the requested optimization level survived source overrides, fixed site defaults, and MAXPCF processing.

New In-feed ads