Page 1 of 1

For a million IFs less

PostPosted: Fri Sep 28, 2018 10:17 pm
by polparioritsas
One of the first you learn in #Cobol, especially back in the day when indexed files where a common practice, is the use of SW-FIRST-READ.

In a program flow most probably there’s a loop on a cursor or a file. Many programmers inside that main loop they use an IF for controlling the first read. For example, if you want to match previous and current row/record. The COBOL code would be something like:

01 SW-FIRST-READ PIC X VALUE ‘Y’.

  88 FIRST-READ-YES   VALUE ‘Y’.
  88 FIRST-READ-NOT   VALUE ‘N’.
MAIN-ROUTE.
   PERFORM READ-ROUTE
   #PERFORM UNTIL EOF
     #IF FIRST-READ-YES
        SET FIRST-READ-NOT TO TRUE
        MOVE CURRENT-RECORD TO PREVIOUS-RECORD
     END-IF
     IF CURRENT-RECORD = PREVIOUS-RECORD
        DISPLAYSAME ACCOUNT’
        PERFORM SAME-ACCOUNT-ROUTE
     ELSE
        DISPLAYNEW ACCOUNT’
        PERFORM NEW-ACCOUNT-ROUTE
     END-IF
     PERFORM READ-ROUTE
   END-PERFORM
  IF EOF AND SW-FIRST-READ
      DISPLAYNO RECORDS/ROWS IN FILE/CURSOR
      PERFORM EMPY-FILE-OR-CURSOR-ROUTE
   END-IF .
READ-ROUTE.
    READ FILE NEXT AT END SET SW-EOF TO TRUE
(OR)
   FETCH CURSOR
   IF SQLCODE = NOT-FOUND-NEXT
      SET SW-EOF TO TRUE
   END-IF
 IF SQLCODE/FILE-STATUS NOT-OK
      ERROR-HANDLING-ROUTE
    END-IF.
 

This is a very common practice with one fault for performance. The IF SW-FIRST-READ will execute as many times as the ROWS/RECORDS of the CURSOR/FILE – 1.000.000 or 50.000.000 times, and IF statement is not a fast one.

My recommendation would have some more code to be written, some paragraph rearrangements and involve a bit more thinking. But it will have 1.000.000 IFs less.

You will have to have separate paragraphs for #READ / #FETCH, for error handling and PERFORM these paragraphs twice, once before the main loop. That one would be the first time and will be executed only once. There’s no need to ask again. The code would look like this:


MAIN-ROUTE.
   PERFORM READ-ROUTE
   IF NOT-EOF
      MOVE CURRENT-RECORD TO PREVIOUS-RECORD
   ELSE
      DISPLAYNO RECORDS/ROWS IN FILE/CURSOR
      PERFORM EMPY-FILE-OR-CURSOR-ROUTE
   END-IF
   PERFORM UNTIL EOF
     IF CURRENT-RECORD = PREVIOUS-RECORD
        DISPLAYSAME ACCOUNT’
        PERFORM SAME-ACCOUNT-ROUTE
     ELSE
        DISPLAYNEW ACCOUNT’
        PERFORM NEW-ACCOUNT-ROUTE
     END-IF
   END-PERFORM
  PERFORM END-ROUTE  .
READ-ROUTE.
   READ FILE NEXT AT END SET SW-EOF TO TRUE
(OR)
   #FETCH #CURSOR
   IF SQLCODE = NOT-FOUND-NEXT
      SET SW-EOF TO TRUE
   END-IF
   IF SQLCODE/FILE-STATUS NOT-OK
      #ERRORHANDLING-ROUTE
    END-IF.
 

Re: For a million IFs less

PostPosted: Sat Sep 29, 2018 12:43 am
by enrico-sorichetti
when You post code, learn how to use the code tag
it will make Your snippet more readable

edited Your post and done it for You

Re: For a million IFs less

PostPosted: Sat Sep 29, 2018 1:43 am
by polparioritsas
thank you.