Binary Truncation

7.3.2.4. Binary Truncation

Figure 7-6 - A Binary Truncation Demo Program

By default, the OpenCOBOL compiler will truncate binary data items to the precision

IDENTIFICATION DIVISION.

indicated by their PICTURE clause. For

PROGRAM-ID. DEMOTRUNC.

example, the following data item will have 2

ENVIRONMENT DIVISION.

bytes of storage allocated for it:

DATA DIVISION.

01 Comp-5-Item PIC 9(3) COMP-5.

WORKING-STORAGE SECTION.

Because of truncation, even though this field

01 Bin-Item-1 PIC 9(3) has enough bits allocated (16) to store values

COMP-5 from 0 to 65535, it will be limited to values of 0

VALUE 32760. to 999 because of its PICTURE.

01 Disp-Item-1 PIC 9(6). Or is it?

PROCEDURE DIVISION. 000-Main.

Take a look at the small demo program shown

MOVE Bin-Item-1 TO Disp-Item-1

here. This program will perform three different

DISPLAY

types of operations against a binary field,

'Bin-Item-1=' Bin-Item-1

displaying the results of each.

' Disp-Item-1=' Disp-Item-1

Here are the results when the program is

END-DISPLAY

compiled (with truncation in-effect by default)

ADD 5 TO Bin-Item-1

and executed:

MOVE Bin-Item-1 TO Disp-Item-1 DISPLAY

Bin-Item-1=760 Disp-Item-1=032760

'Bin-Item-1=' Bin-Item-1

Bin-Item-1=765 Disp-Item-1=032765

' Disp-Item-1=' Disp-Item-1

Bin-Item-1=767 Disp-Item-1=032767

END-DISPLAY MOVE 32767 TO Bin-Item-1

You can see that truncation affected the

MOVE Bin-Item-1 TO Disp-Item-1

DISPLAY statements but appears to have had

DISPLAY

no impact whatsoever on the MOVE and ADD

'Bin-Item-1=' Bin-Item-1

statements. This is the hidden secret about

' Disp-Item-1=' Disp-Item-1

truncation in OpenCOBOL: it doesn’t really

END-DISPLAY

truncate the internally-stored values – it just

STOP RUN.

truncates the DISPLAY of them!

If that same program is recompiled without truncation (by adding the “-fnotrunc” switch to the ‘cobc’ command), the results are as follows:

If this was all there was to the binary truncation issue it

Bin-Item-1=32760 Disp-Item-1=032760

wouldn’t be worth a section in this document. The fact is,

Bin-Item-1=32765 Disp-Item-1=032765

however, that binary truncation has a significant effect on the

Bin-Item-1=32767 Disp-Item-1=032767

performance of OpenCOBOL programs. When binary truncation is in effect, arithmetic operations performed

against all types of numeric data items (even USAGE DISPLAY) are slowed down. Before continuing, it’s worth making the point that we’re NOT talking about astronomical performance degradations

here. Today’s computers are FAST, and a user sitting at the keyboard, running an OpenCOBOL program is unlikely to notice. BUT … if you have an OpenCOBOL program that has to process large amounts of data, performing some significant “number crunching” against that data as it goes, the impact of truncation could become noticeable.

The demo program shown in Figure 7-7 compares the performance of performing arithmetic operations (in a totally non-scientific, non-rigorous way) against USAGE DISPLAY, COMP, COMP-5 and BINARY-xxx 47 numeric data. It was actually my intent when I first wrote the program to merely demonstrate the relative performance differences between the first three types of numeric data storage, and it certainly met that objective.

Imagine my surprise, however, when I discovered that the use of “-fnotrunc” also made a significant difference! Here’s what the program does:

There are four numeric data items in the program – one USAGE DISPLAY, one USAGE COMP, one USAGE

COMP-5 and one USAGE BINARY-LONG. Since the program was run on a computer with an Intel-architecture processor (actually it’s an AMD, but results are identical with Intel) I wanted to see just how much more efficient COMP-5 was over COMP.

Each data item will have 7 added to it ten million times. You’ll see why shortly. The time (to one-one-hundredth of a second) will be retrieved before and after each test and the difference

between the two will be DISPLAYed. This is why the computations were done so many times – it was to make sure the timing was “measurable” with only a 1/100 second “stopwatch”.

OpenCOBOL is retrieving wall-clock time, not actual CPU-used time, so other activities taking place on the computer had to be kept to a minimum while the tests were running. I also ran the tests multiple times, just to make sure I had consistent results (I did). Like I mentioned earlier – this is not a rigorous, scientific benchmark of numeric performance; it’s just a quick-and-dirty comparison.

Figure 7-7 shows the program and the test results received when executing both with and without the “-fnotrunc” switch.

Here are the conclusions I drew from running these tests many times (30). The timings shown are average times from all tests:

With truncation ON: USAGE COMP has a significant performance advantage over USAGE DISPLAY

USAGE COMP-5 has an even greater performance advantage over USAGE COMP, than COMP did over

DISPLAY USAGE BINARY-LONG (and presumably the other BINARY-xxx USAGEs as well) perform identically (within the measurement tolerances of the test) with COMP-5; this should be no surprise since COMP-5 and BINARY-xxx

both allocate data the same way With truncation OFF: There was a huge drop in both USAGE DISPLAY and USAGE COMP timings.

The relative performance advantage of USAGE COMP over USAGE DISPLAY is even larger with truncation off than it was with it on. USAGE COMP-5 and USAGE BINARY-xxx appear to be virtually unaffected by the truncation on/off status, although there was a .01 second increase in average execution time of those tests without truncation over those with truncation. Given the number of times I ran the tests, it’s obvious that something makes COMP- 5/BINARY-xxx run slower without truncation than with it; that difference, however, is so miniscule that I

discount it as being statistically irrelevant 48 .

M y final observation is that I see absolutely no reason whatsoever why the “-fnotrunc” option shouldn’t be used on all OpenCOBOL compilations.

If you want to squeeze every last bit of performance out of your OpenCOBOL programs, don’t forget to investigate the various “–O” (optimization) switches. Actually run programs using various optimization switches (or not) and compare

47 USAGE BINARY-xxx is supposed to store numeric data identically to USAGE COMP- 5, but I felt it couldn’t hurt to check.

48 Remember – that’s a .01 second difference over TEN MILLION iterations! 48 Remember – that’s a .01 second difference over TEN MILLION iterations!

Figure 7-7 - A Non-Scientific Comparison of Numeric Data Item USAGE Performance IDENTIFICATION DIVISION.

Results with truncation

PROGRAM-ID. DEMOMATH.

turned on (the default)

DATA DIVISION. WORKING-STORAGE SECTION.

USAGE DISPLAY: 6.49 SECONDS

01 Begin-Time. USAGE COMP: 2.81 SECONDS

05 BT-HH PIC 9(2). USAGE COMP-5: 0.04 SECONDS

05 BT-MM PIC 9(2). USAGE BINARY: 0.04 SECONDS

05 BT-SS PIC 9(2).

05 BT-HU PIC 9(2).

01 Binary-Item BINARY-LONG SIGNED VALUE 0.

01 Comp-Item COMP PIC S9(9) VALUE 0.

01 Comp-5-Item COMP-5 PIC S9(9) VALUE 0.

Results with truncation

01 Display-Item DISPLAY PIC S9(9) VALUE 0.

t urned off (“-fnotrunc”

01 End-Time.

used on ‘cobc’)

05 ET-HH PIC 9(2).

05 ET-MM PIC 9(2). USAGE DISPLAY: 0.69 SECONDS

05 ET-SS PIC 9(2). USAGE COMP: 0.06 SECONDS

05 ET-HU PIC 9(2). USAGE COMP-5: 0.05 SECONDS

78 Repeat-Count VALUE 10000000. USAGE BINARY: 0.05 SECONDS

01 Time-Diff PIC ZZ9.99. PROCEDURE DIVISION. 010-Test-Usage-DISPLAY.

ACCEPT Begin-Time FROM TIME END-ACCEPT PERFORM Repeat-Count TIMES ADD 7 TO Display-Item END-PERFORM PERFORM 100-Determine-Time-Diff DISPLAY 'USAGE DISPLAY: ' Time-Diff ' SECONDS' END-DISPLAY.

020-Test-Usage-COMP. ACCEPT Begin-Time FROM TIME END-ACCEPT PERFORM Repeat-Count TIMES ADD 7 TO Comp-Item END-PERFORM PERFORM 100-Determine-Time-Diff DISPLAY 'USAGE COMP: ' Time-Diff ' SECONDS' END-DISPLAY.

030-Test-Usage-COMP-5. ACCEPT Begin-Time FROM TIME END-ACCEPT PERFORM Repeat-Count TIMES ADD 7 TO Comp-5-Item END-PERFORM PERFORM 100-Determine-Time-Diff DISPLAY 'USAGE COMP-5: ' Time-Diff ' SECONDS' END-DISPLAY.

040-Test-Usage-BINARY. ACCEPT Begin-Time FROM TIME END-ACCEPT PERFORM Repeat-Count TIMES ADD 7 TO Binary-Item END-PERFORM PERFORM 100-Determine-Time-Diff DISPLAY 'USAGE BINARY: ' Time-Diff ' SECONDS' END-DISPLAY.

099-Done. STOP RUN. 100-Determine-Time-Diff. ACCEPT End-Time FROM TIME END-ACCEPT COMPUTE Time-Diff =

( (ET-HH * 360000 + ET-MM * 6000 + ET-SS * 100 + ET-HU) - (BT-HH * 360000 + BT-MM * 6000 + BT-SS * 100 + BT-HU) ) / 100.