News Headlines
Tech Headlines
Plan Headlines
Front Page
Search the NewsWire

Verb Performance

By Shawn M. Gordon

Bill Seitz of Retriever Interactive recently suggested I do a column showing some of the performance hits made by some of the COBOL verbs such as INSPECT, STRING and UNSTRING. This reminded me of an experience I had years ago with my e-mail product and a template processor I had written for it. You might recall a column I did last year that showed the overhead of using the MOVE FUNCTION CURRENT-DATE verb as opposed to parsing out CALENDAR. Sometimes the benefit of using something like CURRENT-DATE for standardization purposes far outweighs the trivial impact the verb has over a system specific call like CALENDAR.

The way this template processor worked is that it used UNSTRING all over the place to parse out the tokens on a line, allowing me to easily look for keywords. It worked and the code was very simple, in general. However, I have always kept in mind some wisdom I got from Wirt Atmar of AICS about 10 years ago. Wirt at the time said he still had a Series 30 or 33 (I forget which) that he tested all of his code on — because if it ran efficiently there, then it would be fine on anything else.

So up until last year I was still compiling and testing on my old Series 37 to make sure that I wouldn’t have a problem. At the time I wrote the template processor I did it on a Series 70, and it was quite zippy. But once I put it down on the 37, I could almost get a cup of coffee waiting for each field to come up. I then spent a few days re-writing all the parsing routines into in-line PERFORM loops to speed it up, and the difference was dramatic.

These days, with all the fast machines and memory, it may not make much difference anymore —but it’s still worth understanding the overhead associated with how you write code. We are both going to discover the answer to this at the same time, because I am writing the sample programs as I write this to test the timing.

The first test (Figure 1) will be INSPECT versus an in-line PERFORM to find the first blank character in a fairly long string. I’m going to use the same WORKING-STORAGE SECTION for each example. I am using the ACCEPT VAR FROM TIME so that I can get time resolution down to the tenth of a second. Since a single iteration won’t necessarily show a difference, I will perform each function 10,000 times. These tests were run on a Series 996-200.

Figure 1



$CONTROL USLINIT, BOUNDS, POST85
                 IDENTIFICATION DIVISION.
                 PROGRAM-ID. STUFF.
                * Test various cobol functions
                 ENVIRONMENT DIVISION.
                 CONFIGURATION SECTION.
                 DATA DIVISION.
                 WORKING-STORAGE SECTION.
                *
                 01 MY-TIME              PIC X(08)  VALUE SPACES.
                 01 S1                   PIC S9(4)  COMP VALUE 0.
                 01 S2                   PIC S9(4)  COMP VALUE 0.
                 01 S3                   PIC S9(4)  COMP VALUE 0.

                *
                 01 MY-BUFF              PIC X(200) VALUE SPACES.

                 01 DEASSEMBLE-PARMS.
                    03 DP1               PIC X(50)  VALUE SPACES.
                    03 DP2               PIC X(50)  VALUE SPACES.
                    03 DP3               PIC X(50)  VALUE SPACES.
                    03 DP4               PIC X(50)  VALUE SPACES.
                *
                 PROCEDURE DIVISION.
                 A1000-INIT.
                DISPLAY 'ENTER STRING: ' NO ADVANCING.
                      ACCEPT MY-BUFF FREE.
                      ACCEPT MY-TIME FROM TIME.
                      DISPLAY 'Prior to INSPECT: ' MY-TIME.
                      PERFORM 10000 TIMES
                         MOVE ZEROES              TO S1
                         INSPECT MY-BUFF TALLYING S1 FOR CHARACTERS
                                 BEFORE INITIAL " "
                      END-PERFORM.
                      ACCEPT MY-TIME FROM TIME.
                      DISPLAY 'After INSPECT, before PERFORM: ' MY-TIME.
                      PERFORM 10000 TIMES
                         PERFORM VARYING S1 FROM 1 BY 1 UNTIL MY-BUFF(S1:1)
= ' '
                            CONTINUE
                         END-PERFORM
                      END-PERFORM.
                      ACCEPT MY-TIME FROM TIME.
                      DISPLAY 'After PERFORM: ' MY-TIME.
                    STOP RUN.


                :RUN STUFFO

                ENTER STRING:

        FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
                FFFFF SD
                Prior to INSPECT: 08330020
                After INSPECT, before PERFORM: 08330350
                After PERFORM: 08330400
                

As you can see, the inspect takes 3.3 seconds to execute 10,000 times and the PERFRM takes just .1 second to execute. It’s a dramatic difference, but only on a huge number of iterations.

Our next test (Figure 2) will be for UNSTRING. As you can see below, the UNSTRING took 1.7 seconds to execute 10,000 times and the PERFORM loop took only 0.1 second.

Figure 2



      DISPLAY 'ENTER STRING: ' NO ADVANCING.
                      ACCEPT MY-BUFF FREE.
                      ACCEPT MY-TIME FROM TIME.
                      DISPLAY 'Prior to UNSTRING: ' MY-TIME.
                      PERFORM 10000 TIMES
                         UNSTRING MY-BUFF DELIMITED BY "," INTO
DP1 DP2 DP3 DP4
                      END-PERFORM.
                      ACCEPT MY-TIME FROM TIME.
                      DISPLAY 'After UNSTRING, before PERFORM: ' MY-TIME.
                      PERFORM 10000 TIMES
                         MOVE 1                    TO S2
                         PERFORM VARYING S1 FROM 1 BY 1 UNTIL MY-BUFF(S1:1)
= ' '
                            IF MY-BUFF(S1:1) = ','
                               SUBTRACT S2 FROM S1 GIVING S3
                               MOVE MY-BUFF(S2:S3) TO DP1
                               ADD 1 TO S1 GIVING S2
                            END-IF
                         END-PERFORM
                      END-PERFORM.
                      ACCEPT MY-TIME FROM TIME.
                      DISPLAY 'After PERFORM: ' MY-TIME.
                   STOP RUN.

                ENTER STRING: dog,cat,mouse,emu
                Prior to UNSTRING: 08143670
                After UNSTRING, before PERFORM: 08143840
                After PERFORM: 08143850
                

So what do we learn from all this? Apparently the computers have sped up to the point where we don’t have to worry so much about the efficiency of these direct verbs. However, if you are processing a large number of records and using things like INSPECT, STRING and UNSTRING and are running into performance problems, it’s not a bad idea to invest some time to write your own processor. You can even make it a macro so that it’s reusable and easy to implement.

Shawn Gordon, whose S.M. Gordon & Associates firm supplies HP 3000 utilities, has worked with 3000s since 1983.


Copyright The 3000 NewsWire. All rights reserved.