optimizaciÓn-calidadyrendimientoenprogramacióncobol_v02

32
Diseño y Desarrollo Arquitectura y Optimización – Host Calidad y Rendimiento en Programación COBOL Mayo 2008

Upload: dalven666

Post on 13-Aug-2015

618 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

Calidad y Rendimiento en

Programación COBOL

Mayo 2008

Page 2: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 2/32 Mayo de 2008

Índice

1. Analizador COBOL/DB2.................................................................................................................3 2. Versión de COBOL..........................................................................................................................3 3. Instrucciones especialmente consumidoras. ....................................................................................5

3.1. INITIALIZE..............................................................................................................................5 3.2. REMAINDER...........................................................................................................................6

4. Cálculos............................................................................................................................................7 4.1. Factor común. ...........................................................................................................................7 4.2. Uso de constantes......................................................................................................................7 4.3. Funciones. .................................................................................................................................7

5. Tipos de datos. .................................................................................................................................8 6. Instrucciones evitables. ....................................................................................................................9

6.1. Control del FILE STATUS en secuenciales. ............................................................................9 6.2. MOVE de áreas muy grandes. ................................................................................................11 6.3. Instrucciones que no están en su sitio. ....................................................................................12

7. Longitud variable. ..........................................................................................................................12 8. Seguimiento de programas batch. ..................................................................................................13 9. Enfrentamientos. ............................................................................................................................13

9.1. Intersección. ............................................................................................................................14 9.2. Maestro (parcial o completo). .................................................................................................16 9.3. Exclusión.................................................................................................................................16 9.4. Unión.......................................................................................................................................17 9.5. Fichero grande vs Fichero pequeño. .......................................................................................18 9.6. Enfrentamiento de tres ficheros. .............................................................................................18

10. Tablas WORKING.......................................................................................................................21 10.1. Búsquedas Working. .............................................................................................................21 10.2. Índices Working....................................................................................................................22

11. SORT. ..........................................................................................................................................23 11.1. OUTFIL vs INCLUDE. ........................................................................................................23

Anexo I – Guía rápida........................................................................................................................27 Anexo II - FILE STATUS .................................................................................................................29 Anexo III – Funciones intrínsecas .....................................................................................................32

Page 3: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 3/32 Mayo de 2008

0. Introducción. Este documento es un conjunto de recomendaciones para la codificación de Programas COBOL con el objetivo de que consuman la menor CPU y/o ELAPSED TIME posibles.

1. Analizador COBOL/DB2. En primera instancia y como norma general se recomienda seguir las normas ya contempladas en el Anexo “Conjunto de reglas verificadas por el analizador” de la Guía de uso del Analizador de código COBOL/DB2.

2. Versión de COBOL. Es fundamental informarse de la versión sobre la que correrán los programas, que en principio es COBOL ENTERPRISE. El siguiente ejemplo demuestra la importancia de este punto:

01 NUMEROX PIC X(5) VALUE ZEROS. 01 FILLER REDEFINES NUMEROX. 03 NUMERO9 PIC 9(5). 01 CONTADOR PIC 9 VALUE 0. PERFORM UNTIL NUMERO9 > 99999 OR CONTADOR = 5 ADD 1 TO CONTADOR DISPLAY 'CONTADOR:' CONTADOR END-PERFORM.

El campo NUMERO9 es constante y nunca llega a ser > 99999, por lo que el bucle se ejecutará siempre 5 veces, desde CONTADOR = 1 hasta CONTADOR = 5. Eso es así en COBOL II, mientras que COBOL ENTERPRISE da un error grave de compilación (hasta agosto de 2007 daba un error warning avisando de que se ignoraba el PERFORM, y de hecho el bucle no se ejecutaba, pero el procedimiento de compilación fue modificado, por el peligro que ello suponía, para que diera un RC=12):

PP 5655-G53 IBM Enterprise COBOL for z/OS 3.4.1 ARQPG3173-E The result of the comparison of operands NUMERO9 and 99999 is known at compile time, based on the attributes of the operands. Unconditional code was generated.

Esto se debe a que COBOL ENTERPRISE entiende que el campo NUMERO9, por ser PIC 9(5), nunca podrá ser > 99999 (lo cual sería falso si tuviera caracteres no numéricos, como p.e. HIGH-VALUES). En cambio COBOL II compila correctamente y ejecuta esto:

Page 4: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 4/32 Mayo de 2008

PP 5668-958 IBM VS COBOL II Release 4.0 09/15/92 CONTADOR:1 CONTADOR:2 CONTADOR:3 CONTADOR:4 CONTADOR:5

Lo mismo sucede con este ejemplo:

01 CONTADOR PIC 9(2) VALUE 0. IF CONTADOR > 100 DISPLAY 'MAYOR' ELSE DISPLAY 'NO MAYOR' END-IF.

Compilación COBOL ENTERPRISE con resultado RC=12: Se descarta el IF, al tomarlo como falso, y su DISPLAY:

IF CONTADOR > 100 The result of the comparison of operands CONTADOR and 100 is known at compile time, based on the attributes of the operands. Unconditional code was generated. DISPLAY 'MAYOR' Code from "DISPLAY (line 31.01)" to "DISPLAY (line 31.01)" can never be executed and was therefore discarded. ELSE DISPLAY 'NO MAYOR' END-IF.

Compilación COBOL II: mismo mensaje pero con resultado RC=04 (warning en el IF) y ejecución:

IF CONTADOR > 100 The result of the comparison of operands CONTADOR and 100 is known at compile time, based on the attributes of the operands. Unconditional code was generated. DISPLAY 'MAYOR' ELSE DISPLAY 'NO MAYOR' END-IF. NO MAYOR

Page 5: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 5/32 Mayo de 2008

3. Instrucciones especialmente consumidoras.

3.1. INITIALIZE Esta instrucción hay que utilizarla con precaución o evitarla en lo posible. Si se ejecuta un sólo INITIALIZE su consumo es despreciable respecto al total del programa. El problema surge si se ejecuta millones de veces, p.e. una vez por cada registro, y/o dentro de bucles, etc. Internamente el INITIALIZE de un área se convierte en tantas instrucciones MOVE como campos haya dentro del área. Como esos MOVE’s son diferentes (SPACES/ZEROS) en función de la PICTURE del campo a limpiar (ese es el objetivo del INITIALIZE), el COBOL tiene que examinar en tiempo de ejecución cuál es la PICTURE de cada campo para entonces hacer MOVE ZEROS o MOVE SPACES. Así, el INITIALIZE es más costoso:

a) Cuantas más veces se ejecuta. b) Cuantos más campos haya dentro del área que se inicializa. La existencia de un

OCCURS multiplica este efecto. Este ejemplo demuestra el ahorro de CPU en un programa que sólo hace INITIALIZE o MOVE, en función de un parámetro. Son varias ejecuciones de un programa que tiene un bucle para ejecutar N veces una instrucción o la otra: Nº Ejecución Nº iteraciones Nº campos CPU INITIALIZE CPU MOVE % Ahorro (long.tot.5000) (minutos) (minutos) 1 50.000.000 1 0,38 0,35 8 2 50.000.000 5 0,47 0,42 10 3 100.000.000 5 0,95 0,84 11 4 100.000.000 10 1,06 0,91 14 Este es el programa en la Ejecución Nº 4:

01 CAMPO. 03 CAMPO1 PIC X(1000). 03 CAMPO2 PIC 9(10). 03 CAMPO3 PIC X(2000). 03 CAMPO4 PIC 9(10). 03 CAMPO5 PIC X(30). 03 CAMPO6 PIC 9(9) COMP-3. 03 CAMPO7 PIC X(41). 03 CAMPO8 PIC 9(8) COMP. 03 CAMPO9 PIC X(900). 03 CAMPO10 PIC X(1000).

Page 6: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 6/32 Mayo de 2008

a) PERFORM 100000000 TIMES INITIALIZE CAMPO END-PERFORM. b) PERFORM 100000000 TIMES MOVE SPACES TO CAMPO1 CAMPO3 CAMPO5 CAMPO7 CAMPO9 CAMPO10 MOVE 0 TO CAMPO2 CAMPO4 CAMPO6 CAMPO8 END-PERFORM.

El caso b ahorra un 14,2% de CPU sobre el a, y aún puede mejorarse con este bucle, donde el ahorro es del 32%:

b) PERFORM 100000000 TIMES MOVE SPACES TO CAMPO limpia todo el área MOVE 0 TO CAMPO2 CAMPO4 CAMPO6 CAMPO8 END-PERFORM.

3.2. REMAINDER Muchos programas o rutinas realizan cálculos de dígitos de control (NIF, código de cliente, CCC, etc.), bien sea para generarlo (altas) o para comprobarlo (consultas). Normalmente estos algoritmos utilizan el resto de una división:

01 CLIENTE PIC 9(9) COMP VALUE 123456. 01 COCIENTE PIC 9(9) COMP VALUE 0. 01 RESTO PIC 9(9) COMP VALUE 0.

Usando DIVIDE:

DIVIDE CLIENTE BY 12 GIVING COCIENTE REMAINDER RESTO

Usando COMPUTE es más rápido:

COMPUTE RESTO = CLIENTE - (12 * (CLIENTE / 12))

Como siempre el ahorro de CPU adquiere importancia cuando el cálculo se realiza muchas veces, ya sea por estar en un bucle, o por hacerlo para cada registro de entrada, etc. En el ejemplo anterior: Nº Ejecución Nº iteraciones CPU DIVIDE CPU COMPUTE % Ahorro (minutos) (minutos) 1 100.000.000 0,24 0,16 33

Page 7: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 7/32 Mayo de 2008

4. Cálculos.

4.1. Factor común. El Optimizador de COBOL no saca factor común en las operaciones aritméticas, por lo que hay que hacerlo mediante código:

MOVE 0 TO TOTAL. PERFORM VARYING I FROM 1 BY 1 UNTIL I = 1000 COMPUTE TOTAL = TOTAL + (CAMPO(I) * TIPO) END-PERFORM.

Este algoritmo es mucho más eficiente:

MOVE 0 TO TOTAL. PERFORM VARYING I FROM 1 BY 1 UNTIL I = 1000 COMPUTE TOTAL = TOTAL + CAMPO(I) END-PERFORM. COMPUTE TOTAL = TOTAL * TIPO

Como regla general, este tipo de fallos puede detectarse cuando se observa que dentro del bucle aparece un campo (TIPO) que no cambia de valor, o que incluso es una constante.

4.2. Uso de constantes. Es frecuente la tendencia a escribir las constantes a la derecha de una expresión:

COMPUTE IMPORTE = CAMPO * 5.

Sin embargo eso desaprovecha ciertas funciones del Optimizador, cosa que no ocurriría si las constantes se colocasen a la izquierda, especialmente cuando hay más de una constante. Ejemplo (V=Variable, C=Constante):

Peor: V1 + C1 + V2 + C2 + V3 + C3 Mejor: (C1 + C2 + C3) + V1 + V2 + V3

4.3. Funciones. Frecuentemente se desarrollan rutinas, algoritmos, bucles, y funciones en general, para realizar ciertos cálculos que COBOL ENTERPRISE ya incorpora como funciones (“funciones intrínsecas”):

01 CAMPO1 PIC X(6) VALUE '123 '. 01 CAMPO2 PIC 9(6) VALUE 0.

Page 8: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 8/32 Mayo de 2008

01 CAMPO3 PIC X(6) VALUE 'hola'. 01 CAMPO4 PIC 9(3) VALUE 100. 01 CAMPO5 PIC 9(3) VALUE 120. 01 CAMPO6 PIC 9(3). DISPLAY 'CAMPO1 = ' CAMPO1. DISPLAY 'CAMPO2 = ' CAMPO2. COMPUTE CAMPO2 = FUNCTION NUMVAL-C(CAMPO1). DISPLAY 'CAMPO2 = ' CAMPO2. DISPLAY FUNCTION UPPER-CASE(CAMPO3). COMPUTE CAMPO6 = FUNCTION MAX(CAMPO4 CAMPO5). DISPLAY 'CAMPO6 = ' CAMPO6. CAMPO1 = 123 CAMPO2 = 000000 CAMPO2 = 000123 Rellenado con ceros a la izda. HOLA Convertido a mayúsculas CAMPO6 = 120 El mayor valor

Algunas funciones permiten manejar fechas, lo que puede ahorrar llamadas a rutinas:

01 AAAAMMDD PIC 9(8). 01 NUMERO PIC S9(9). MOVE FUNCTION CURRENT-DATE(1:8) TO AAAAMMDD. DISPLAY 'AAAAMMDD = ' AAAAMMDD. COMPUTE NUMERO = FUNCTION INTEGER-OF-DATE(AAAAMMDD). ADD 90 TO NUMERO. COMPUTE AAAAMMDD = FUNCTION DATE-OF-INTEGER(NUMERO). DISPLAY 'AAAAMMDD = ' AAAAMMDD. AAAAMMDD = 20080306 Fecha actual AAAAMMDD = 20080604 Le ha sumado 90 días (04-06-2008)

5. Tipos de datos. Se deben asignar a los campos de WORKING las PICTURE’s adecuadas al uso que se les va a dar. Salvo algunas excepciones, el tipo de datos más rápido para realizar cálculos es COMP, aún mejor si tiene signo (S9(n) COMP). El siguiente tipo en velocidad es COMP-3, y el más lento DISPLAY. Para campos COMP el ranking de velocidad es el siguiente, de mayor a menor, si se usa la opción TRUNC(OPT) del Compilador, por lo que, en lo posible, se deberá usar el formato que esté más arriba:

Page 9: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 9/32 Mayo de 2008

1. S9(1) COMP a S9(4) COMP 2. S9(5) COMP a S9(8) COMP 3. S9(10) COMP a S9(17) COMP 4. S9(9)COMP observar que es más lento que S9(10) COMP 5. S9(18)COMP

Para campos DISPLAY este es el ranking:

1. 9(1) a 9(15), con número impar de dígitos 2. 9(2) a 9(16), con número par de dígitos 3. 9(17) a 9(18)

Para COMP-3 se mantiene la misma regla, ya que un número impar de dígitos es más eficiente.

6. Instrucciones evitables.

6.1. Control del FILE STATUS en secuenciales. Es frecuente controlar el FILE STATUS en las operaciones con ficheros secuenciales, pero algunos de esos controles son innecesarios. Si además se ejecutan millones de veces se consigue consumir CPU sin obtener ventajas a cambio:

WRITE registro FROM reg-copy. IF FS-FICHERO NOT = ‘00’ …… END-IF.

Si el registro a grabar ya no cabe porque el fichero se ha llenado, se devuelve un FILE STATUS = ‘34’, y si el programa no tiene excepciones (DECLARATIVES) se produce automáticamente un abend B37, lo que impide precisamente la comprobación del FILE STATUS, ya que el programa no llega a ejecutar el IF. Por tanto es suficiente con:

WRITE registro FROM reg-copy.

Por otra parte, la comprobación de FILE STATUS = ‘00’ tampoco garantiza siempre la finalización correcta de la operación:

SELECT SALIDA ASSIGN TO FICHESAL FILE STATUS IS FS-SALIDA. FD SALIDA LABEL RECORD STANDARD RECORDING MODE F BLOCK CONTAINS 0 RECORDS. 01 R-SALIDA PIC X(120). ……

Page 10: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 10/32 Mayo de 2008

01 FS-SALIDA PIC XX VALUE '00'. …… OPEN OUTPUT SALIDA. DISPLAY 'FS OPEN OUTPUT = ' FS-SALIDA. WRITE R-SALIDA FROM …… DISPLAY 'FS WRITE = ' FS-SALIDA. //PASO1 EXEC PGM=PROGRAMA //FICHESAX DD DSN=D319.CFOP.NUEVO.SALI1, // DISP=(,CATLG,DELETE), // SPACE=(CYL,(50,50),RLSE), // DCB=(RECFM=FB,BLKSIZE=0,LRECL=120)

El DDNAME del fichero SALIDA (FICHESAL) está mal escrito en el JCL (FICHESAX), o lo que es lo mismo, la DDNAME FICHESAL no está en el JCL. Para ficheros de salida esto no se detecta con el FILE STATUS, ni siquiera con el de la OPEN, ya que el Sistema Operativo asigna al fichero un DSN temporal y el programa realmente graba en dicho fichero, aunque sólo si está activa la opción CBLQDA del runtime:

IGD101I SMS ALLOCATED TO DDNAME (SALIDA ) DSN (SYS08064.T162737.RA000.A708427X.R0228272 ) STORCLAS (TEMPORAL) MGMTCLAS ( ) DATACLAS (DEFECTO) VOL SER NOS= TEM3AI FS OPEN OUTPUT = 00 FS WRITE = 00

Y al contrario, un FILE STATUS <> ‘00’ no implica que sea erróneo; p.e. el FILE STATUS = ‘02’ en el READ de un fichero indexado indica que hay más registros con la misma clave, pero la READ se ha ejecutado correctamente. Estos son algunos ejemplos del funcionamiento de FILE STATUS cuando se producen errores:

• Fichero de entrada: DDNAME del JCL coincide con el indicado en el programa (nombre de conexión), pero el fichero no existe o no se puede localizar (no catalogado, etc.): Se produce JCL ERROR con RC=FLUSH por DATA SET NOT FOUND.

• Fichero de entrada: La longitud real no coincide con la especificada en el

programa: RC=00 a menos que se cancele. Se puede detectar en la OPEN INPUT (FILE STATUS = ‘39’). Si a pesar de la OPEN errónea se llega a ejecutar el READ, éste devuelve FILE STATUS = ‘47’ (fichero no abierto).

• Fichero de entrada: El nombre de conexión indicado en el programa no está en el

JCL: RC=00 a menos que se cancele. Se pude detectar en la OPEN INPUT (FILE STATUS = ‘35’). La READ daría ‘47’ (fichero no abierto). Observar que si falta la DD es lo mismo que si está mal escrita.

Page 11: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 11/32 Mayo de 2008

• Fichero de entrada: Se intenta hacer READ después de haberse producido AT END: El AT END devuelve FILE STATUS = ‘10’, y los siguientes READ devolverían FILE STATUS = ‘46’, hasta que el paso cancela por tiempo, por exceso de líneas, etc. El dejar de leer queda en manos de la lógica del programa.

• Fichero de salida: La longitud no coincide con la especificada en el programa:

OPEN OUTPUT = ‘39’, WRITE = ‘48’. El paso da RC=00 a menos que se cancele por programa.

• Fichero de salida: La DDNAME no consta en el JCL o está mal escrita: Se crea

automáticamente un fichero temporal y aparentemente todo termina bien (caso visto anteriormente).

• Fichero de salida: El fichero se llena: Caso visto anteriormente.

En COBOL, el resultado de cada operación realizada con ficheros se coloca en el campo del FILE STATUS antes de ejecutarse cualquier declaración de errores o el INVALID KEY/AT END asociados a la instrucción. Significa p.e. que cuando se ejecuta el AT END ya se ha colocado el valor ‘10’ en el FILE STATUS. De hecho el AT END es opcional y en su lugar puede preguntarse por el valor ‘10’:

READ FILEA INTO W-FILEA. IF FS-FILEA = ‘10’ ……

6.2. MOVE de áreas muy grandes. Los movimientos de áreas muy grandes consumen mucha CPU, lo que puede ser grave si además se ejecutan muchas veces. En este código se hace una copia de AREA en AREA2, con mismo formato, para usarla más adelante:

IF …… ADD 1 TO CONTA PERFORM …… MOVE AREA TO AREA2 END-IF. MOVE AREA2 TO AREA.

El último MOVE se está ejecutando sin necesidad cuando se ha ejecutado también el MOVE anterior, ya que en este caso las dos áreas ya son iguales antes de hacer el segundo MOVE.

Page 12: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 12/32 Mayo de 2008

Insertando un ELSE se pueden eliminar millones de instrucciones respetando la funcionalidad, y de paso aportando claridad:

IF …… ADD 1 TO CONTA PERFORM …… MOVE AREA TO AREA2 ELSE MOVE AREA2 TO AREA END-IF.

6.3. Instrucciones que no están en su sitio. Una cuestión tan simple como colocar las instrucciones en el sitio correcto puede ahorrar mucha CPU cuando las iteraciones son muchas:

• Cabeceras de listado (fecha, página, etc.). Si la fecha es siempre la misma se debe mover al principio del programa, no en el típico párrafo CABECERAS del salto de página. El número de página sí se moverá en ese párrafo.

• Llamadas a rutinas. Si el programa tiene que llamar una vez a una rutina, la

llamada tendrá que estar en el sitio adecuado. Frecuentemente se observan programas que hacen la CALL cuando se necesita el dato, aunque ya se haya obtenido antes.

• Etc.

7. Longitud variable. Al crear un fichero de longitud variable bloqueado, codificar en el programa la cláusula APPLY WRITE-ONLY. La opción explícita en un programa prima sobre la opción del compilador AWO, por tanto la opción NOAWO del Compilador no tiene efecto sobre un programa que tenga APPLY WRITE-ONLY. AWO mejora mucho el tiempo de proceso cuando el fichero de salida tiene mucha variación de longitudes, pues ahorra operaciones I/O’s:

• Sin AWO, el buffer de escritura se lleva al fichero cuando en el buffer ya no cabría el registro más grande.

Page 13: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 13/32 Mayo de 2008

• Con AWO, el buffer de escritura se lleva al fichero cuando en el buffer ya no cabe el registro siguiente.

8. Seguimiento de programas batch. Es frecuente el uso de contadores de registros leídos y grabados para mostrarlos al final del programa, pero no lo es tanto el uso de DISPLAY ‘INICIO PGM XXXXXXXX’ y ‘FIN PGM XXXXXXXX’. Estos dos displays no consumen nada ni ocupan spool, por ser únicos, pero facilitan mucho el seguimiento del job y la localización de los displays. Los contadores usados deben ser del tipo PIC S9(8) COMP, ya que este formato admite números de hasta más de 2.000 millones. También se recomienda poner al inicio del programa un DISPLAY que muestra la versión del mismo, concretamente la fecha y hora en que fue compilado:

01 COMPILA PIC X(30) VALUE SPACES. MOVE WHEN-COMPILED TO COMPILA. DISPLAY ‘INICIO PGM XXXXXXXX’. DISPLAY ‘VERSION ‘ COMPILA. INICIO PGM XXXXXXXX VERSION 03/06/0810.34.31 MM/DD/AAhh.mm.ss conviene mostrarlo en todos los programas como “DD-MM-AAAA (hh:mm:ss)”.

9. Enfrentamientos. Este tipo de programas son muy comunes en la instalación, por lo que es fundamental ejecutar únicamente las instrucciones necesarias. Podemos clasificar los cruces en 5 tipos. Cada círculo representa un fichero. La intersección de los dos ficheros es el conjunto de registros que tienen correspondencia en ambos (“claves” iguales). La parte sombreada, en cada caso, indica los registros que se quieren tratar (normalmente será llevarlos a salida). Se da por hecho que los ficheros de entrada vienen ordenados por lo que llamamos “clave”, ya sea ascendente o descendentemente. Ante un fichero de entrada vacío se debe actuar como sigue:

• Si es un fichero que debiera tener algún registro, se debe cancelar la ejecución del programa según el procedimiento establecido (llamada a rutina general de abend), avisando con DISPLAY explicativo de la situación, ya que se trata de un error grave.

Page 14: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 14/32 Mayo de 2008

Como excepción, si esto se detecta en una rutina llamada, en lugar de cancelar hay que comunicárselo al programa llamante, para que éste actúe en consecuencia.

• Si se trata de un fichero que puede tener o no registros, el hecho de que no los

tenga no es un error. Por tanto hay que actuar normalmente, es decir, como si se hubiera alcanzado el “fin fichero”, ya que, después de todo, eso es lo que ha sucedido.

Esta actuación ante ficheros vacíos no es válida sólo para los enfrentamientos, sino que es aplicable a cualquier tipo de programa Batch.

9.1. Intersección.

DEFINICIÓN Pasan los que están en los dos ficheros [A and B]. TERMINACIÓN Parar cuando se acabe cualquiera de los dos ficheros (no los dos):

01 FS-FILEA PIC XX. 88 FIN-FILEA VALUE '10'. 01 FS-FILEB PIC XX. 88 FIN-FILEB VALUE '10'. PERFORM PROCESO UNTIL FIN-FILEA OR FIN-FILEB.

Eso puede evitar millones de lecturas, pues se ha comprobado que muchos programas siguen leyendo del otro fichero para luego descartar sus registros. Este método de lectura es tan común como ineficiente:

READ FILEA INTO W-FILEA AT END lectura SET FIN-FILEA TO TRUE si fin, activa flag MOVE HIGH-VALUES TO CLAVE-FILEA si fin, prepara clave máxima END-READ. IF FS-FILEA NOT = ‘00’ AND FS-FILEA NOT = ‘10’ comprobación de errores DISPLAY ‘ERROR……’ PERFORM CANCELAR END-IF. IF NOT FIN-FILEA si no fin, suma a contador y prepara clave ADD 1 TO CONTADOR-FILEA

Page 15: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 15/32 Mayo de 2008

MOVE CLIENTE TO CLAVE-FILEA END-IF.

Por un lado se emplea FIN-FILEA conjuntamente con HIGH-VALUES, cuando con uno de ellos ya se sabe que es fin fichero. Pero además el HIGH-VALUES no tiene utilidad en este caso, ya que el cruce de tipo INTERSECCIÓN se va a detener en cuanto se acabe cualquiera de los dos ficheros (el HIGH-VALUES es útil cuando el proceso debe continuar aunque uno de los dos se haya acabado, y sólo si los ficheros vienen ordenados ascendentemente, ya que en caso contrario hay que usar LOW-VALUES). En definitiva, casi todo el código está orientado a detectar el fin fichero, cuando precisamente éste se va a producir sólo una vez. Y todo esto es aplicable además al segundo fichero. El siguiente código cumple la misma función con 4 líneas:

READ FILEA INTO W-FILEA NOT END ADD 1 TO CONTADOR-FILEA MOVE CLIENTE TO CLAVE-FILEA END-READ.

El NOT END se activa únicamente si el READ se ha ejecutado bien (FILE STATUS = ‘00’). O bien, de forma alternativa

READ FILEA INTO W-FILEA IF FS-FILEA = ‘00’ ADD 1 TO CONTADOR-FILEA MOVE CLIENTE TO CLAVE-FILEA END-IF END-READ.

En la gran mayoría de casos, donde los ficheros vienen ordenados ascendentemente, el enfrentamiento típico, en el que la cardinalidad de los ficheros A:B es 1:1 es el siguiente:

IF CLAVE-FILEA = CLAVE-FILEB PERFORM TRATAR…… PERFORM LEER-FILEA PERFORM LEER-FILEB(*) ELSE IF CLAVE-FILEA < CLAVE-FILEB PERFORM LEER-FILEA ELSE PERFORM LEER-FILEB END-IF END-IF.

Page 16: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 16/32 Mayo de 2008

(*) El fichero del que hay que leer es uno y/u otro según sea la cardinalidad de los ficheros A:B (1:1, 1:N, etc.). De hecho el proceso puede acelerarse si esta cardinalidad se conoce previamente.

9.2. Maestro (parcial o completo). a) b)

DEFINICIÓN

a) Pasan los que están en A y no en B [A and ¬B]. b) Pasan los que están en A [A].

TERMINACIÓN Parar cuando se acabe A:

PERFORM PROCESO UNTIL FIN-FILEA.

Si se acaba B hay que seguir el proceso, pero ya no hace falta preguntar continuamente IF CLAVE-FILEA = CLAVE-FILEB. En este caso hay que derivar el proceso a un párrafo que trate el resto de A directamente, sin enfrentar, y al no haber enfrentamiento tampoco es necesario el uso de HIGH-VALUES.

9.3. Exclusión.

DEFINICIÓN Pasan los que están en A y no en B, y los que están en B y no en A [(A and ¬B) or (B and ¬A)]. TERMINACIÓN Hay que esperar a que se acaben los dos ficheros:

PERFORM PROCESO UNTIL FIN-FILEA AND FIN-FILEB.

Page 17: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 17/32 Mayo de 2008

Aquí puede ser útil el uso de HIGH-VALUES, pero tampoco es necesario. Cuando se acabe un fichero se sabe que todo lo que quede del otro debe ir a salida, por tanto se puede derivar el proceso a un párrafo específico. Esto tiene más importancia cuanta mayor sea la diferencia de tamaño de los ficheros, ya que si uno es muy pequeño respecto al otro, el primero normalmente se acabará antes, y entonces el proceso comparará las claves inútilmente tantas veces como registros queden en el grande.

9.4. Unión.

DEFINICIÓN Pasan todos los de A y los de B [A or B]. TERMINACIÓN Hay que esperar a que se acaben los dos ficheros:

PERFORM PROCESO UNTIL FIN-FILEA AND FIN-FILEB.

También aquí, para evitar el uso de HIGH-VALUES y no tener que preguntar millones de veces si un fichero se ha acabado, podemos acelerar el proceso: 1º empezamos un bucle hasta que se acabe uno de los dos:

PERFORM PROCESO UNTIL FIN-FILEA OR FIN-FILEB.

2º vemos cuál se ha acabado:

IF FIN-FILEA PERFORM PROCESO-B UNTIL FIN-FILEB ELSE PERFORM PROCESO-A UNTIL FIN-FILEA END-IF.

3º entramos en uno de los dos párrafos específicos para grabar todo lo que falte:

PROCESO-A. (bucle de grabar/leer sin preguntar nada) PROCESO-B. (bucle de grabar/leer sin preguntar nada)

Page 18: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 18/32 Mayo de 2008

Esto está planteado desde un punto de vista general, pero evidentemente habrá casos especiales. Por ejemplo, cuando se produce la igualdad de claves (CLAVE-A = CLAVE-B), y una vez hecho el tratamiento (grabar ese registro, etc.), el fichero o ficheros de los que hay que leer (A y/o B) depende de la cardinalidad de los ficheros.

9.5. Fichero grande vs Fichero pequeño. Un caso especial es cuando uno de los dos ficheros es muy voluminoso respecto al otro. En este caso conviene hacer el siguiente proceso:

1. Cargar el fichero pequeño ordenado por su clave de enfrentamiento en WORKING y hacer CLOSE. Contemplar un número suficiente de ocurrencias y definir como índice de la tabla el campo de enfrentamiento (ver capítulo siguiente).

2. En lugar de hacer enfrentamiento de claves, buscar en la tabla la clave leída del

fichero grande, utilizando búsqueda binaria.

9.6. Enfrentamiento de tres ficheros. Otro caso especial es cuando debemos enfrentar tres ficheros. El proceso dependerá del tipo de enfrentamiento (intersección, etc.). Este ejemplo cubriría un caso común, que es aquél en que se deben tratar los registros cuyas claves figuran en los tres ficheros, ordenados ascendentemente; el proceso se puede detener nada más alcanzar el final de uno de ellos:

* *** AREAS DE ENTRADA 01 W-FILEA. 03 ... PIC X(..). 03 CLIENTE-FILEA PIC 9(9). 03 ... PIC X(..). 01 W-FILEB. 03 CLIENTE-FILEB PIC 9(9) COMP. 03 ... PIC X(..). 01 W-FILEC. 03 ... PIC X(..). 03 CLIENTE-FILEC PIC 9(8). * *** CLAVES ENFRENTAMIENTO

Page 19: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 19/32 Mayo de 2008

01 A. 03 CLIENTEA PIC 9(9) VALUE 0. 01 B. 03 CLIENTEB PIC 9(9) VALUE 0. 01 C. 03 CLIENTEC PIC 9(9) VALUE 0. * *** FILE STATUS 01 FS-FILEA PIC XX VALUE '00'. 88 FIN-FILEA VALUE '10'. 01 FS-FILEB PIC XX VALUE '00'. 88 FIN-FILEB VALUE '10'. 01 FS-FILEC PIC XX VALUE '00'. 88 FIN-FILEC VALUE '10'. PERFORM INICIO. PERFORM PROCESO UNTIL FIN-FILEA OR FIN-FILEB OR FIN-FILEC. PERFORM FIN. INICIO. OPEN INPUT los tres ficheros. PERFORM LEERA. PERFORM LEERB. PERFORM LEERC. LEERA. READ FILEA INTO W-FILEA END-READ IF FS-FILEA = ‘00’ MOVE CLIENTE-FILEA TO CLIENTEA END-IF. LEERB. READ FILEB INTO W-FILEB END-READ IF FS-FILEB = ‘00’ MOVE CLIENTE-FILEB TO CLIENTEB END-IF. LEERC. READ FILEC INTO W-FILEC END-READ IF FS-FILEC = ‘00’

MOVE CLIENTE-FILEC TO CLIENTEC END-IF. * *** ENFRENTAMIENTO. * Para el caso de intersección, sólo interesan los registros que tengan correspondencia en los tres ficheros. Por tanto cuando un fichero sea “menor” que otro, ya se sabe que hay que leer del primero. El proceso consiste en enfrentar A y B, y sólo cuando A=B se comprueba C. Este es el proceso más sencillo: PROCESO. IF A < B PERFORM LEERA ELSE IF A > B PERFORM LEERB ELSE (A=B) IF A < C PERFORM LEERA ELSE

Page 20: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 20/32 Mayo de 2008

IF A > C PERFORM LEERC ELSE (A=B=C) PERFORM TRATAR END-IF END-IF END-IF END-IF. TRATAR. WRITE FROM…… PERFORM LEERA. PERFORM LEERB. PERFORM LEERC.

Para ficheros muy grandes puede aplicarse la siguiente variante. Consiste en evitar la ejecución de muchos IF’s, pero la mejora no es sustancial porque en estos casos el tiempo de ejecución se emplea en la propia lectura de los ficheros, más que en tiempo de proceso. Se basa en lo siguiente: Cuando en el ejemplo de arriba se sabe que se va a cumplir muchas veces A>C (último IF), cada vez que se ejecute PERFORM LEERC vuelve a entrar en PROCESO y a preguntar por los IF’s de arriba (A<B, etc.), IF’s que se sabe que no se van a cumplir porque acabamos de leer C (y no cambia la situación AB). Por tanto, para evitar esas instrucciones, cada PERFORM LEER se puede convertir en un bucle de lecturas hasta que deje de darse la condición por la que se inició el bucle: …… IF A > C PERFORM LEERC UNTIL A NOT > C ELSE PERFORM TRATAR ……

Así lo único que haría será leer y comprobar esa condición (y no las condiciones de arriba). Pero no hay que olvidar que el proceso es hasta el final de algún fichero, por tanto al escribir bucles hay que considerarlo, y por eso el PERFORM correcto sería este: …… PERFORM LEERC UNTIL (A NOT > C) OR (FIN-FILEC) ……

Una optimización adicional puede realizarse si se conoce a priori la abundancia o escasez de coincidencias de claves (ficheros muy similares o muy diferentes respectivamente). El método consiste en escribir primero el caso más frecuente, de manera que si se sabe que hay coincidencia en muchas claves, conviene preguntar primero por A=B=C. Así, en la siguiente entrada al bucle la ejecución llegará lo antes posible a la condición que va a cumplirse:

Page 21: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 21/32 Mayo de 2008

IF A = B IF A = C (A=B=C) PERFORM TRATAR ELSE IF A < C PERFORM LEERA ELSE (A>C) PERFORM LEERC END-IF END-IF ELSE IF A < B PERFORM LEERA ELSE (A>B) PERFORM LEERB END-IF END-IF.

10. Tablas WORKING.

10.1. Búsquedas Working. Cuando una tabla de WORKING se ha cargado usando algún criterio de ordenación, la búsqueda binaria (SEARCH ALL) es mucho más rápida que la búsqueda secuencial (SEARCH), y más rápida cuanto más grande sea la tabla. El criterio de ordenación puede haberse empleado en un campo o en más de uno, y puede haber sido ASCENDING o DESCENDING (o unos campos ASCENDING y otros DESCENDING). En caso de usar búsqueda secuencial se recomienda dentro de lo posible cargar las ocurrencias más usadas al principio de la tabla (o al final de la tabla si la búsqueda se hace empezando por el final). En caso de usar búsqueda secuencial se recomienda guardar un contador de ocurrencias ocupadas a la hora de cargar la tabla, para que luego la búsqueda no tenga que recorrer la tabla completa. Algunas funciones intrínsecas de COBOL ENTERPRISE pueden facilitar operaciones con tablas:

01 TABLA. 03 FILLER PIC X(3) VALUE '001'. 03 FILLER PIC X(3) VALUE '002'. 03 FILLER PIC X(3) VALUE '015'. 03 FILLER PIC X(3) VALUE '016'. 03 FILLER PIC X(3) VALUE '003'. 01 FILLER REDEFINES TABLA. 03 IMPORTE PIC 9(3) OCCURS 5. 01 SUMA PIC S9(8) COMP VALUE 0.

Page 22: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 22/32 Mayo de 2008

COMPUTE SUMA = FUNCTION SUM(IMPORTE(ALL)) DISPLAY SUMA. 000000037

Esta es la diferencia de CPU utilizando la función SUM y utilizando un PERFORM VARYING para sumar las 5 ocurrencias, repitiendo el cálculo en ambos casos muchas veces para que la medición sea significativa: Nº Ejecución Nº iteraciones PERFORM FUNCION % Ahorro (minutos) (minutos) 1 100.000.000 0,32 0,23 28 2 200.000.000 0,65 0,46 29

10.2. Índices Working. Al usar un índice (USAGE IS INDEX) en lugar de un contador de ocurrencias, se evitan conversiones internas. Los índices ya tienen calculado el desplazamiento desde el inicio de la tabla, mientras que los contadores o subíndices son números de ocurrencia que se tienen que convertir en desplazamiento en tiempo de ejecución. Cuando la tabla ya tiene definido un índice, el uso de un segundo índice elimina por completo las conversiones de datos en tiempo de ejecución:

01 TABLA. 03 CAMPO PIC…… OCCURS 10 INDEXED BY INX-1. 01 INX-2 USAGE IS INDEX. SET INX-1 TO 10. SET INX-2 TO INX-1. PERFORM VARYING INX-1 FROM 1 BY 1 UNTIL INX-1 > INX-2 DISPLAY CAMPO (INX-1) …… END-PERFORM.

Para subíndices, usar PIC S9(4) COMP (o PIC S9(8) COMP si se requieren más dígitos). El rango de valores que pueden contener los campos binarios PIC S9(n) COMP es:

• N entre 1 y 4 -32.768 a +32.767 • N entre 5 y 9 -2.147.483.648 a +2.147.483.647

Por tanto un PIC S9(8) COMP es el formato idóneo para todo tipo de contadores (registros leídos, etc.), o S9(4) COMP si se tiene la seguridad de que es suficiente.

Page 23: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 23/32 Mayo de 2008

11. SORT.

11.1. OUTFIL vs INCLUDE. La función del parámetro INCLUDE es llevar a la salida los registros que cumplan una condición, clasificando o no. La función del parámetro OUTFIL es básicamente la misma, con la diferencia de que el OUTFIL está orientado a generar más de un fichero de salida, pero permite ejecutarlo para generar un solo fichero. Cuando en un SORT se clasifica un fichero al mismo tiempo que se seleccionan registros, la secuencia de los procesos internos del SORT indica que:

• Usando el parámetro OUTFIL, primero clasifica todo el fichero y después selecciona los registros.

• Usando el parámetro INCLUDE, primero selecciona los registros y después los clasifica.

OUTFIL clasifica todos 001800 //SORTIN DD * 002000 21 002100 30 002101 51 002110 10 002200 40 002700 //SALIDA DD DSN=D319.SORT.OUTFIL, 002800 // DISP=(,CATLG,DELETE),SPACE=(TRK,(1,1),RLSE), 003000 // DCB=(RECFM=FB,LRECL=80,BLKSIZE=0,DSORG=PS) 003100 //SYSIN DD * 003200 SORT FIELDS=(1,2,CH,A) 003300 OUTFIL FNAMES=SALIDA,INCLUDE=(2,1,CH,EQ,C'1') ICE055I 0 INSERT 0, DELETE 0 elimina 0 antes de ordenar ICE054I 0 RECORDS - IN: 5, OUT: 5 van 5 al proceso de ordenación ICE227I 0 SALIDA : DELETED = 3, REPORT = 0, DATA = 2 ICE228I 0 SALIDA : TOTAL IN = 5, TOTAL OUT = 2 van 2 a SALIDA ICE134I 0 NUMBER OF BYTES SORTED: 400 ordena 5x80=400 bytes ICE199I 0 MEMORY OBJECT STORAGE USED = 1M BYTES ICE188I 0 DATA SPACE STORAGE USED = 0K BYTES ICE052I 0 END OF DFSORT BROWSE D319.SORT.OUTFIL Line 00000000 Col 001 080 Command ===> Scroll ===> CSR ********************************* Top of Data ********************************** 21 00200000 51 00210100 ******************************** Bottom of Data ********************************

Page 24: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 24/32 Mayo de 2008

Recursos empleados: --TIMINGS (MINS.)-- PROCSTEP RC EXCP CPU SRB CLOCK SERV SORT01 00 402 .00 .00 .02 7248

INCLUDE clasifica los necesarios 001800 //SORTIN DD * 002000 21 002100 30 002101 51 002110 10 002200 40 002710 //SORTOUT DD DSN=D319.SORT.INCLUDE, 002800 // DISP=(,CATLG,DELETE),SPACE=(TRK,(1,1),RLSE), 003000 // DCB=(RECFM=FB,LRECL=80,BLKSIZE=0,DSORG=PS) 003100 //SYSIN DD * 003200 SORT FIELDS=(1,2,CH,A) 003300 INCLUDE COND=(2,1,CH,EQ,C'1') ****** **************************** Bottom of Data **************************** ICE080I 0 IN MAIN STORAGE SORT ICE055I 0 INSERT 0, DELETE 3 elimina 3 antes de ordenar ICE054I 0 RECORDS - IN: 5, OUT: 2 van 2 al proceso de ordenación ICE134I 0 NUMBER OF BYTES SORTED: 160 ordena 2x80=160 bytes ICE180I 0 HIPERSPACE STORAGE USED = 0K BYTES ICE188I 0 DATA SPACE STORAGE USED = 0K BYTES ICE052I 0 END OF DFSORT ******************************** BOTTOM OF DATA ******************************** BROWSE D319.SORT.INCLUDE Line 00000000 Col 001 080 Command ===> Scroll ===> CSR ********************************* Top of Data ********************************** 21 00200000 51 00210100 ******************************** Bottom of Data ******************************** Recursos empleados: --TIMINGS (MINS.)-- PROCSTEP RC EXCP CPU SRB CLOCK SERV SORT01 00 74 .00 .00 .00 488

Con ficheros grandes la diferencia de consumo puede ser considerable. Estos son los recursos empleados con un fichero de un millón de registros de longitud 300:

EXCP CPU CLOCK SERV BYTES SORTED OUTFIL 612 0,03 0,43 952.000 302.547.600 INCLUDE 596 0,01 0,32 31.125 54.371.400

Como conclusión no se debe usar OUTFIL para generar un solo fichero.

Page 25: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 25/32 Mayo de 2008

Para ordenar un fichero generando dos, INCLUDE ahorra CPU mientras que OUTFIL ahorra ELAPSED TIME:

Page 26: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 26/32 Mayo de 2008

OUTFIL

1.000.000 regs de long 300

A 740.000 regs

B 260.000 regs

Pos. 20 = ‘0’ Pos. 20 <> ‘0’

Paso único

INCLUDE

Paso 2

INCLUDE

Paso 1

Pos. 20 = ‘0’

B 260.000 regs

A 740.000 regs

1.000.000 regs de long 300

Pos. 20 <> ‘0’

CPU CLOCK OUTFIL 0,04 0,50 Tot. OUTFIL 0,04 0,50 INCLUDE 1 0,01 0,40 INCLUDE 2 0,01 0,35 Tot. INCLUDE 0,02 0,75

Page 27: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 27/32 Mayo de 2008

Anexo I – Guía rápida

1) Usar EVALUATE en lugar de IF cuando los casos a evaluar son 4 o más. 2) No hacer INITIALIZE de un área de entrada si a continuación se va a hacer

READ sobre la misma área. 3) No hacer INITIALIZE de un área de salida si a continuación se van a rellenar

todos los campos para hacer WRITE. Si no se van a rellenar todos, hacer un sólo INITIALIZE y guardar el área para usarlo con MOVE las siguientes veces.

4) No mover al registro de WORKING el área leída si ya se lee con READ INTO. 5) Evitar controles dobles en la detección del fin fichero. Muchas veces se utiliza

MOVE ‘S’ TO FIN-FICHERO a la vez que MOVE HIGH-VALUES TO CLAVE, cuando probablemente con uno de los dos es suficiente.

6) Usar PERFORM in-line cuando el PERFORM no va a ser llamado desde varios

sitios y sólo si las instrucciones del PERFORM son pocas (hasta 10). Si va a ser llamado desde varios sitios y/o contiene muchas instrucciones, conviene hacerlo out-of-line (normal) para escribirlo sólo una vez, y también por claridad.

7) Para manejar tablas de WORKING, usar PERFORM n TIMES en lugar de usar un

contador cuando el número de iteraciones es conocido (aunque sea una variable). Esto evita el uso del contador explícito, optimiza el formato del contador implícito, y evita errores en el código.

8) En general, la estructuración correcta de los párrafos de PROCEDURE no sólo

facilita el mantenimiento, sino que aprovecha al máximo la potencia del Optimizador, que se verá muy limitado si el programa no está bien estructurado.

9) Tanto en ficheros secuenciales de entrada como de salida, indicar BLOCK

CONTAINS 0 RECORDS en el programa. En ficheros de salida, poner BLKSIZE=0 en el JCL, para permitir que el Sistema Operativo establezca el bloqueo óptimo (ficheros de salida) o que utilice el bloqueo ya existente (ficheros de entrada).

10) La compresión de ficheros de salida (DATACLAS=EXTCOMPS) implica aumento

del consumo de CPU tanto en su generación como en su lectura, pero a cambio reduce el tiempo ELAPSED. Por tanto, la compresión de ficheros debe aplicarse a ficheros voluminosos y JOBs en los que prime la reducción de elapsed frente al consumo de CPU.

Page 28: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 28/32 Mayo de 2008

11) Eliminar o comentar párrafos que no se utilicen, para no agrandar el módulo sin necesidad.

Page 29: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 29/32 Mayo de 2008

Anexo II - FILE STATUS Table 36. File status key values and meanings

High-order digit

Meaning

Low-order digit

Meaning

0 No further information

2

This file status value applies only to indexed files with alternate keys that allow duplicates. The input-output statement was successfully executed, but a duplicate key was detected. For a READ statement, the key value for the current key of reference was equal to the value of the same key in the next record within the current key of reference. For a REWRITE or WRITE statement, the record just written created a duplicate key value for at least one alternate record key for which duplicates are allowed.

4

A READ statement was successfully executed, but the length of the record being processed did not conform to the fixed file attributes for that file.

5

An OPEN statement is successfully executed but the referenced optional file is unavailable at the time the OPEN statement is executed. The file has been created if the open mode is I-O or EXTEND. This does not apply to VSAM sequential files.

0

Successful completion

7

For a CLOSE statement with the NO REWIND, REEL/UNIT, or FOR REMOVAL phrase or for an OPEN statement with the NO REWIND phrase, the referenced file was on a non-reel/unit medium.

0

A sequential READ statement was attempted and no next logical record existed in the file because the end of the file had been reached. Or the first READ was attempted on an optional input file that was unavailable.

1

At-end condition

4

A sequential READ statement was attempted for a relative file, and the number of significant digits in the relative record number was larger than the size of the relative key data item described for the file.

1

A sequence error exists for a sequentially accessed indexed file. The prime record key value was changed by the program between the successful execution of a READ statement and the execution of the next REWRITE statement for that file. Or the ascending requirements for successive record key values were violated.

2

An attempt was made to write a record that would create a duplicate key in a relative file. Or an attempt was made to write or rewrite a record that would create a duplicate prime record key or a duplicate alternate record key without the DUPLICATES phrase in an indexed file.

3

An attempt was made to randomly access a record that does not exist in the file. Or a START or random READ statement was attempted on an optional input file that was unavailable.

2

Invalid key condition 4 An attempt was made to write beyond the externally defined boundaries of

Page 30: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________ ___ _____________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 30/32 Mayo de 2008

______ __________________________________

a relative or indexed file. Or a sequential WRITE statement was attempted for a relative file and the number of significant digits in the relative record number was larger than the size of the relative key data item described for the file.

0 No further information

4

A permanent error exists because of a boundary violation; an attempt was made to write beyond the externally defined boundaries of a sequential file.

5

An OPEN statement with the INPUT, I-O, or EXTEND phrase was attempted on a nonoptional file that was unavailable.

7

An OPEN statement was attempted on a file that would not support the open mode specified in the OPEN statement. Possible violations are: ° The EXTEND or OUTPUT phrase was specified but the file would not support write operations. ° The I-O phrase was specified but the file would not support the input and output operations permitted. ° The INPUT phrase was specified but the file would not support read operations.

8 An OPEN statement was attempted on a file previously closed with lock.

3

Permanent error condition

9

The OPEN statement was unsuccessful because a conflict was detected between the fixed file attributes and the attributes specified for that file in the program. These attributes include the organization of the file (sequential, relative, or indexed), the prime record key, the alternate record keys, the code set, the maximum record size, the record type (fixed or variable), and the blocking factor.

1 An OPEN statement was attempted for a file in the open mode.

2 A CLOSE statement was attempted for a file not in the open mode.

3

For a mass storage file in the sequential access mode, the last input-output statement executed for the associated file prior to the execution of a REWRITE statement was not a successfully executed READ statement. For relative and indexed files in the sequential access mode, the last input-output statement executed for the file prior to the execution of a DELETE or REWRITE statement was not a successfully executed READ statement.

4

A boundary violation exists because an attempt was made to rewrite a record to a file and the record was not the same size as the record being replaced. Or an attempt was made to write or rewrite a record that was larger than the largest or smaller than the smallest record allowed by the RECORD IS VARYING clause of the associated file-name.

4

Logic error condition

6

A sequential READ statement was attempted on a file open in the input or I-O mode and no valid next record had been established because:

Page 31: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 31/32 Mayo de 2008

° The preceding READ statement was unsuccessful but did not cause an at-end condition. ° The preceding READ statement caused an at-end condition.

7

The execution of a READ statement was attempted on a file not open in the input or I-O mode.

8

The execution of a WRITE statement was attempted on a file not open in the I-O, output, or extend mode.

9

The execution of a DELETE or REWRITE statement was attempted on a file not open in the I-O mode.

d0

° For multithreading only: A CLOSE of a VSAM or QSAM file was attempted on a thread that did not open the file. ° Without multithreading: For VSAM only: See the information about VSAM return codes in the Enterprise COBOL Programming Guide.

1 For VSAM only: Password failure

2 Logic error

3 For all files, except QSAM: Resource unavailable

5 For all files except QSAM: Invalid or incomplete file information

6

For VSAM file: An OPEN statement with the OUTPUT phrase was attempted, or an OPEN statement with the I-O or EXTEND phrase was attempted for an optional file but no DD statement was specified for the file. For QSAM file: An OPEN statement with the OUTPUT phrase was attempted, or an OPEN statement with the I-O or EXTEND phrase was attempted for an optional file but no DD statement was specified for the file and the CBLQDA(OFF) runtime option was specified.

7

For VSAM only: OPEN statement execution successful: File integrity verified

9

Implementor-defin condition

8

Open failed due to the invalid contents of an environment variable specified in a SELECT ... ASSIGN clause or due to dynamic allocation failure. For more information about the contents of environment variables, see "ASSIGN clause" in topic 4.2.3.

Page 32: OPTIMIZACIÓN-CalidadyRendimientoenProgramaciónCOBOL_v02

Diseño y Desarrollo Arquitectura y Optimización – Host

______________________________________________________________________________________ OPTIMIZACIÓN-Calidad y Rendimiento en Programación COBOL_v02 32/32 Mayo de 2008

Anexo III – Funciones intrínsecas ACOS ANNUITY ASIN ATAN CHAR COS CURRENT-DATE DATE-OF-INTEGER DATE-TO-YYYYMMDD DATEVAL DAY-OF-INTEGER DAY-TO-YYYYDDD DISPLAY-OF FACTORIAL INTEGER INTEGER-OF-DATE INTEGER-OF-DAY INTEGER-PART LENGTH LOG LOG10 LOWER-CASE MAX MEAN MEDIAN

MIDRANGE MIN MOD NATIONAL-OF NUMVAL NUMVAL-C ORD ORD-MAX ORD-MIN PRESENT-VALUE RANDOM RANGE REM REVERSE SIN SQRT STANDARD-DEVIATION SUM TAN UNDATE UPPER-CASE VARIANCE WHEN-COMPILED YEAR-TO-YYYY YEARWINDOW

Referencias: • Enterprise COBOL for z/OS Language Reference Version 4 Release 1 • Enterprise COBOL for z/OS Programming Guide Version 4 Release 1 • IBM Enterprise COBOL Version 3 Release 1 Performance Tuning • Smart DFSORT Tricks