Παρασκευή 28 Σεπτεμβρίου 2018

For a million IFs less

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

        DISPLAY ‘SAME ACCOUNT’

        PERFORM SAME-ACCOUNT-ROUTE

     ELSE

        DISPLAY ‘NEW ACCOUNT’

        PERFORM NEW-ACCOUNT-ROUTE

     END-IF

     PERFORM READ-ROUTE

   END-PERFORM

  IF EOF AND SW-FIRST-READ

      DISPLAY ‘NO 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

      DISPLAY ‘NO RECORDS/ROWS IN FILE/CURSOR’

      PERFORM EMPY-FILE-OR-CURSOR-ROUTE

   END-IF

   PERFORM UNTIL EOF

     IF CURRENT-RECORD = PREVIOUS-RECORD

        DISPLAY ‘SAME ACCOUNT’

        PERFORM SAME-ACCOUNT-ROUTE

     ELSE

        DISPLAY ‘NEW 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.

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου