Optimization and Debugging Problems

Q. I’ve been trying to debug an ILE program that’s been running for some time. Recently, I recreated the program with full optimization to improve performance. But now the debugger doesn’t work. What am I doing wrong?

A. When you optimize a module, the system streamlines the module to make the runtime performance as fast as possible (a nanosecond here, a nanosecond there…). As you’ve discovered, though, optimization can have adverse side effects when you are debugging the program or service program.

Optimization may rearrange or eliminate some statements altogether. Consequently, field values presented by the debugger, as well as breakpoints and step locations, may be inaccurate. Optimization will also affect the accuracy of the DUMP operation and error handling routines (e.g., Monitor groups, *PSSR and INFSR subroutines).

There are three levels of optimization, set by the OPTIMIZE keyword in H-specs (or in the CRTRPGMOD and CRTBNDRPG commands):

  • OPTIMIZE(*NONE) is the default value. The compiler performs no optimization on the code. This option allows you to debug the program accurately, with the debugger presenting correct current field values.
  • OPTIMIZE(*BASIC) performs some optimization on the compiled code. The debugger will let you display variables, but the displayed value may not be the current value. The debugger will also allow variable changes, but you may encounter unexpected results if you try to use the changed variables.
  • OPTIMIZE(*FULL) generates the most efficient code — and the compile process also takes longer. The program should run faster than with either of the other two options. The debugger will let you see (but not change) field values; but the debugger may not show you the correct current field values.

I’m not a big fan of optimization, because I don’t believe the nearly imperceptible performance improvements justify the debugging problems. Also, the RPG IV Reference and the CL Reference have conflicting information about the effects of optimization. Optimization works best with call-intensive programs; it does not improve the performance of file I/O. In rare cases, optimization may actually make the program slower. I usually just leave the default OPTIMIZE(*NONE).

If you do choose to optimize, some data items can “opt out” of the optimization process; use the NOOPT D-spec keyword to prevent optimization of those data items that you do not want to optimize. Using this option will cure the innacuracy problem (for those data items only).

The DSPMOD, DSPPGM, and DSPSRVPGM commands will show you the current level of optimization for an object. You can change optimization levels with the CHGMOD, CHGPGM, or CHGSRVPGM commands; these commands support the levels already discussed, but also add other options:

  • OPTIMIZE(*NONE|*NO|10) — These options are equivalent, and are discussed above. OPTIMIZE(*NO) is used only by the CHGPGM command.
  • OPTIMIZE(*BASIC|20) — These options are equivalent, and are discussed above.
  • OPTIMIZE(*FULL|30) — These options are equivalent, and are discussed above.
  • OPTIMIZE(*YES|40) — This is the highest possible optimization level. In addition to all level 30 optimization, level 40 optimization prevents call and instruction tracing. OPTIMIZE(*YES) is used only by the CHGPGM command.