Sunday, February 2, 2025

A Matter of Time - Part 2 - COBOL

A Matter of Time - Part 1 - Introduction

Back again to build a version of the TDF_LAP() Timing function in COBOL. This is a set of 21 timing entries used to easily monitor timings for embedded or stand-alone routines or SQL statements.

Above: LEGO Guy inspecting the World Time Zones before warming up with some COBOL.

Flashback: LEGO Guy Loves Assembler

Of course the LEGO Guy loves Assembler - virtually building programs brick by brick - but he also likes to warm up with other languages - this time COBOL. After building the lapse routine - TDF-LAP - he'll give it a quick test run. Just a main process that calls another one - with the nested timings produced for each.

Sample Log Output:

This version displays the level along with BEG/END times, lapsed time and the message.

TDF-LAP Function (Procedure) - TDFPROC.CPY

The input parameters consist of an operation code - BEG or END, a timing level - zero thru 20, and a message to print on the END operation. The routine will also populate output fields for the difference in seconds and the difference in the format HHHH:MI:SS.SSSSS - these can be used as needed (or ignored).

*The function is part of the TDFPROC.CPY Copybook (uses TDFWORK.CPY for working storage)

      *****************************************************************
      *    TDF LAP - LAPSE BETWEEN BEGIN/END TIMES (SQL TIMINGS)      *
      *****************************************************************
      *                                                               *
      *    FIELD              I/O  DESCRIPTION                        *
      *    -----------------  ---  ---------------------------------- *
      *    TDX-LAP-OPER        I   OPERATION TYPE (BEG/END)           *
      *    TDX-LAP-LEV         I   LAPSE INDEX SET (0 THRU 20)        *
      *    TDX-LAP-MSG         I   DISPLAY MESSAGE TEXT               *
      *    TDX-LAP-DIFF        O   BEG/END LAPSE IN SECONDS           *
      *    TDX-LAP-TXT-HMS     O   BEG/END LAPSE IN HHHH:MM:SS.SSSSS  *
      *                                                               *
      *****************************************************************
      *                                                               *
      *    EXAMPLE:                                                   *
      *    ---------------------------------------------------------- *
      *    MOVE 0              TO TDX-LAP-LEV                         *
      *    MOVE 'BEG'          TO TDX-LAP-OPER                        *
      *    PERFORM TDF-LAP                                            *
      *    <snip>                                                     *
      *    MOVE 0              TO TDX-LAP-LEV                         *
      *    MOVE 'END'          TO TDX-LAP-OPER                        *
      *    MOVE 'PROCESS-MAIN' TO TDX-LAP-MSG                         *
      *    PERFORM TDF-LAP                                            *
      *    ---------------------------------------------------------- *
      *    RESULTS:                                                   *
      *    L(00) BEG(2024:12:17_16:41:42) END(2024:12:17_16:41:43) -  *
      *          HMS(0000:00:01.35000) MSG: PROCESS-MAIN              *
      *    ---------------------------------------------------------- *
      *         *SINGLE LINE DISPLAYED FOR EACH NESTED LEVEL*         *
      *****************************************************************

       TDF-LAP.
           
           IF TDX-LAP-LEV-OK
               
              COMPUTE TDX-LAP-IDX         = TDX-LAP-LEV + 1
              
              MOVE FUNCTION CURRENT-DATE TO TDX-LAP-END(TDX-LAP-IDX)
              
              IF TDX-LAP-OPER-END
                 
                 MOVE TDX-LAP-BEG(TDX-LAP-IDX) TO TDX-SEC-IN
                 PERFORM TDF-SECONDS
                 MOVE TDX-SEC-OUT TO TDX-LAP-BEG-SEC
                 
                 MOVE TDX-SEC-IN( 1:4) TO TDX-LAP-TXT-BEG-Y
                 MOVE TDX-SEC-IN( 5:2) TO TDX-LAP-TXT-BEG-M
                 MOVE TDX-SEC-IN( 7:2) TO TDX-LAP-TXT-BEG-D
                 MOVE TDX-SEC-IN( 9:2) TO TDX-LAP-TXT-BEG-H
                 MOVE TDX-SEC-IN(11:2) TO TDX-LAP-TXT-BEG-I
                 MOVE TDX-SEC-IN(13:2) TO TDX-LAP-TXT-BEG-S

                 
                 MOVE TDX-LAP-END(TDX-LAP-IDX) TO TDX-SEC-IN
                 PERFORM TDF-SECONDS
                 MOVE TDX-SEC-OUT TO TDX-LAP-END-SEC
                 
                 MOVE TDX-SEC-IN( 1:4) TO TDX-LAP-TXT-END-Y
                 MOVE TDX-SEC-IN( 5:2) TO TDX-LAP-TXT-END-M
                 MOVE TDX-SEC-IN( 7:2) TO TDX-LAP-TXT-END-D
                 MOVE TDX-SEC-IN( 9:2) TO TDX-LAP-TXT-END-H
                 MOVE TDX-SEC-IN(11:2) TO TDX-LAP-TXT-END-I
                 MOVE TDX-SEC-IN(13:2) TO TDX-LAP-TXT-END-S
                 
                 COMPUTE TDX-LAP-DIFF = TDX-LAP-END-SEC
                                      - TDX-LAP-BEG-SEC
                 
                 MOVE TDX-LAP-DIFF TO TDX-HMS-SEC
 
                PERFORM TDF-HMS

                 MOVE TDX-LAP-LEV TO TDX-LAP-TXT-LEV
                 MOVE TDX-HMS-TXT TO TDX-LAP-TXT-HMS
                 MOVE TDX-LAP-MSG TO TDX-LAP-TXT-MSG

                 DISPLAY TDX-LAP-TXT
                 
              END-IF
              
              MOVE FUNCTION CURRENT-DATE TO TDX-LAP-BEG(TDX-LAP-IDX)              
              
           ELSE
              DISPLAY '***ERROR - LEVELS 0 THRU 20 ONLY***'  
           END-IF
           .
       TDF-LAP-EXIT.
           EXIT.

      *****************************************************************

TDF-SECONDS Function - Convert Full Date/Time to Seconds

An additional function - TDF-SECONDS - is used to convert the dates to seconds. The intrinsic function INTEGER-OF-DATE returns the number of days since January 1, 1601 for both BEG/END values. The days are converted to seconds with a full day being removed. The time (Hours, minutes, seconds) are then converted and added to the total seconds. This allows an accurate lapsed time to be calculated by the TDF-LAP primary function.Yet one more function is utilized to convert the lapsed seconds into HHHH:MI.SS.SSSSS format - TDF-HMS.

      *****************************************************************
      *    TDF SECONDS - CONVERT FULL DATE FIELD TO SECONDS           *
      *****************************************************************
      *                                                               *
      *    FIELD              I/O  DESCRIPTION                        *
      *    -----------------  ---  ---------------------------------- *
      *    TDX-SEC-IN          I   FULL 20 CHARACTER DATE/TIME FIELD  *
      *    TDX-SEC-OUT         O   CONVERSION TO SECONDS              *
      *                                                               *
      *****************************************************************
      *                                                               *
      *    EXAMPLE:                                                   *
      *    ---------------------------------------------------------- *
      *    MOVE FUNCTION CURRENT-DATE TO TDX-SEC-IN                   *
      *    PERFORM TDF-SECONDS                                        *
      *    DISPLAY 'SECONDS: ' TDX-SEC-OUT                            *
      *    ---------------------------------------------------------- *
      *    RESULTS: 2024121715132474+050 => 013379008404.74000        *
      *                                                               *
      *****************************************************************
               
       TDF-SECONDS.
           
           COMPUTE TDX-SEC-INT
                 = FUNCTION INTEGER-OF-DATE(TDX-SEC-DATE)

           COMPUTE TDX-SEC-OUT
                 = (TDX-SEC-INT * (24*60*60))
                 - (24*60*60)
                 + (TDX-SEC-HH * 3600)
                 + (TDX-SEC-MI * 60)
                 + (TDX-SEC-SS)
                 + (TDX-SEC-MS / 100)
           .
       TDF-SECONDS-EXIT.
           EXIT.

      *****************************************************************
 
TDF-HMS Function - Format Lapsed Seconds (HMS)

This stand-alone function simply converts seconds into a more readable format - Hours, Minutes and Seconds. This will appear on the TDF-LAP Timing Log Output.

      *****************************************************************
      *    TDF HMS - CONVERT SECONDS TO HHHH:MM:SS.SSSSS FORMAT       *
      *****************************************************************
      *                                                               *
      *    FIELD              I/O  DESCRIPTION                        *
      *    -----------------  ---  ---------------------------------- *
      *    TDX-HMS-SEC         I   NUMBER OF SECONDS                  *
      *    TDX-HMS-TXT         O   OUTPUT STRING: HHHH:MM:SS.SSSSS    *
      *                                                               *
      *****************************************************************
      *                                                               *
      *    EXAMPLE:                                                   *
      *    ---------------------------------------------------------- *
      *    MOVE 22506.256          TO TDX-HMS-SEC                     *
      *    PERFORM TDF-HMS                                            *
      *    DISPLAY " OUT: " TDX-HMS-TXT                               *
      *    ---------------------------------------------------------- *
      *    RESULTS:  0006:15:06.25600 (22506.256 SECONDS)             *
      *                                                               *
      *****************************************************************

        TDF-HMS.

           COMPUTE TDX-HMS-HH  = TDX-HMS-SEC / 3600
           
           COMPUTE TDX-HMS-SEC = TDX-HMS-SEC
                               - (TDX-HMS-HH * 3600)
                               
           COMPUTE TDX-HMS-MM  = TDX-HMS-SEC / 60
           
           COMPUTE TDX-HMS-SEC = TDX-HMS-SEC
                               - (TDX-HMS-MM * 60)
           
           COMPUTE TDX-HMS-SS  = TDX-HMS-SEC

           MOVE TDX-HMS-HH    TO TDX-HMS-TXT-HH
           MOVE TDX-HMS-MM    TO TDX-HMS-TXT-MM
           MOVE TDX-HMS-SS    TO TDX-HMS-TXT-SS
                      
           .
       TDF-HMS-EXIT.
           EXIT.

      *****************************************************************
 
TDFWORK.CPY - Supporting Fields for TDFPROC.CPY Routines.

The working storage fields/arrays are contained in the TDFWORK.CPY copybook.

      *****************************************************************
      *    TDF FUNCTION PARAMETERS / WORKING STORAGE                  *
      *****************************************************************

       01  TDX-HMS-PARMS.
           05  TDX-HMS-SEC            PIC 9(12)V9(5) COMP-3.
           05  TDX-HMS-HH             PIC 9(6)       COMP-3.
           05  TDX-HMS-MM             PIC 9(3)       COMP-3.
           05  TDX-HMS-SS             PIC 9(3)V9(5)  COMP-3.
           05  TDX-HMS-TXT.
               10  TDX-HMS-TXT-HH     PIC 9(4).
               10  FILLER             PIC X          VALUE ':'.
               10  TDX-HMS-TXT-MM     PIC 9(2).
               10  FILLER             PIC X          VALUE ':'.
               10  TDX-HMS-TXT-SS     PIC 9(2).9(5).

       01  TDX-SECONDS-PARMS.
           05  TDX-SEC-INT            PIC  9(8).
           05  TDX-SEC-OUT            PIC  9(16)V9(5) COMP-3.
           05  TDX-SEC-IN.
               10  TDX-SEC-DATE       PIC  9(8).
               10  TDX-SEC-TIME.
                   15  TDX-SEC-HH     PIC  9(2).
                   15  TDX-SEC-MI     PIC  9(2).
                   15  TDX-SEC-SS     PIC  9(2).
                   15  TDX-SEC-MS     PIC  9(2).
               10  TDX-SEC-GMT        PIC S9(4).

       01  TDX-LAP-PARMS.
           05  TDX-LAP-OPER           PIC  X(3).
               88  TDX-LAP-OPER-BEG   VALUE 'BEG'.
               88  TDX-LAP-OPER-END   VALUE 'END'.
           05  TDX-LAP-LEV            PIC  99.
               88  TDX-LAP-LEV-OK     VALUES 0 THRU 20.
           05  TDX-LAP-MSG            PIC  X(50).
           05  TDX-LAP-BEG-SEC        PIC  9(12)V9(5) COMP-3.
           05  TDX-LAP-END-SEC        PIC  9(12)V9(5) COMP-3.
           05  TDX-LAP-DIFF           PIC  9(12)V9(5) COMP-3.
           05  TDX-LAP-IDX            PIC  99.
           05  TDX-LAP-MTX            OCCURS 21 TIMES.
               10  TDX-LAP-BEG        PIC  X(20).
               10  TDX-LAP-END        PIC  X(20).
           05  TDX-LAP-TXT.
               10  FILLER             PIC  X(2) VALUE 'L('.
               10  TDX-LAP-TXT-LEV    PIC  99.
               10  FILLER             PIC  X(6) VALUE ') BEG('.
               10  TDX-LAP-TXT-BEG-Y  PIC  9999.
               10  FILLER             PIC  X    VALUE ':'.
               10  TDX-LAP-TXT-BEG-M  PIC  99.
               10  FILLER             PIC  X    VALUE ':'.
               10  TDX-LAP-TXT-BEG-D  PIC  99.
               10  FILLER             PIC  X    VALUE '_'.
               10  TDX-LAP-TXT-BEG-H  PIC  99.
               10  FILLER             PIC  X    VALUE ':'.
               10  TDX-LAP-TXT-BEG-I  PIC  99.
               10  FILLER             PIC  X    VALUE ':'.
               10  TDX-LAP-TXT-BEG-S  PIC  99.
               10  FILLER             PIC  X(6) VALUE ') END('.
               10  TDX-LAP-TXT-END-Y  PIC  9999.
               10  FILLER             PIC  X    VALUE ':'.
               10  TDX-LAP-TXT-END-M  PIC  99.
               10  FILLER             PIC  X    VALUE ':'.
               10  TDX-LAP-TXT-END-D  PIC  99.
               10  FILLER             PIC  X    VALUE '_'.
               10  TDX-LAP-TXT-END-H  PIC  99.
               10  FILLER             PIC  X    VALUE ':'.
               10  TDX-LAP-TXT-END-I  PIC  99.
               10  FILLER             PIC  X    VALUE ':'.
               10  TDX-LAP-TXT-END-S  PIC  99.
               10  FILLER             PIC  X(6) VALUE ') HMS('.
               10  TDX-LAP-TXT-HMS    PIC  X(16).
               10  FILLER             PIC  X(7) VALUE ') MSG: '.
               10  TDX-LAP-TXT-MSG    PIC  X(50).

      *****************************************************************


Test all 21 nested timings:

Here's a simple COBOL procedure that loops 21 times to populate BEG times for nested levels 0 thru 20. Then it loops an additional 21 times to populate the END times for levels 20 down to 0. A log entry will be printed for each END operation. The LAPSE-LOOP just creates a delay - otherwise the timings will vary in microseconds only.

           MOVE 0               TO TDX-LAP-LEV
           PERFORM UNTIL TDX-LAP-LEV > 20
              MOVE 'BEG'        TO TDX-LAP-OPER
              PERFORM TDF-LAP
              ADD 1             TO TDX-LAP-LEV
              PERFORM LAPSE-LOOP
           END-PERFORM

           PERFORM LAPSE-LOOP

           MOVE 21              TO TDX-LAP-LEV
           PERFORM UNTIL TDX-LAP-LEV <= 0
              PERFORM LAPSE-LOOP
              SUBTRACT 1      FROM TDX-LAP-LEV
              MOVE 'END'        TO TDX-LAP-OPER
              MOVE 'LEVEL TEST' TO TDX-LAP-MSG
              PERFORM TDF-LAP
           END-PERFORM

Full Test Output:

Running the test program TDDATE through OpenCobolIDE - the results are printed to the log.


Success! BEG/END times are registered for each level along with lapsed time. The first test loop set the BEG times while the second test loop marked the END and produced the output. Each level listed is a subset of the next with 20 being the lowest nest and 0 the primary. The entry levels can be used in any fashion - nested or not.

That's the end of the COBOL Timing Demonstration - Up next PC/370 Assembler.