"Cosa" de Negro
febrero 16, 2005
 
Optimizacion I
El tema optimización es muy largo, asi que iré comentando algunos procedimientos que sigo para optimizar mi propio código y el de revisiones que hago.

Pero primero qué es optimización ?
Según el diccionario de la Real Academia Española: Buscar la mejor manera de realizar una actividad.

Significa hacer un mismo trabajo con menor consumo de recursos.
La optimización es un proceso que requiere de análisis, pruebas y estadísticas.

En estos primeros comentarios voy a concentrarme en optimizaciones de velocidad de ejecución.

Seguramente seré muy repetitivo, pero así como un corredor de autos de carrera no solo tiene que saber conducir bien, tambien debe conocer y saber administrar los límites de su auto, y cuanto más conoce del funcionamiento y de los materiales y de la resistencia de los mismos, tendrá mejores oportunidades de sacar esa diferencia que lo hará ganar.

Así que una vez más le recomendaré leer el documento sobre PCODE que se encuentra en PuertoSUR en el apartado Secciones, Documentos de PuertoSUR.

La optimización más gruesa puede hacerse a nivel PRG siguiendo las siguientes reglas:

a) No evaluar funciones innecesarias en bucles FOR-NEXT, WHILE
Ej: FOR n:=1 TO LEN( aArray ) - 1
En cada iteración del bucle, se evalúa la función LEN() y la operación resta, pudiendo evitarse de la siguiente forma:
FOR n := 1 TO nLen

b) Reducir las ramas innecesarias en DO CASE o IF-ELSEIF.
DO CASE
CASE "condicion poco probable"
CASE "condicion medio probable"
CASE "condicion muy probable"
ENDCASE

es mejor hacer
DO CASE
CASE "condicion muy probable"
CASE "condicion medio probable"
CASE "condicion poco probable"
ENDCASE

c) Usar asignaciones INLINE cuando sea posible.
En lugar de hacer:
nAt := AT( "x", cText )
If nAt > 0

No tenga miedo a hacer:
If (nAt := AT( "x", cText )) > 0

d) No usar IIF() cuando se puede usar IF-ENDIF.
Un ejemplo de lo que no se debe hacer, es el comando DEFAULT de FW que genera este código.
cParam := IIF( cParam == NIL, cParam, "" )
y lo óptimo habría sido
IF cParam == NIL; cParam := ""; ENDIF

en el ejemplo no óptimo, siempre se ejecuta la asignación del datos sobre la variable cParam, incluso cuando no lo tiene que cambiar, se le asigna su propio dato.

e) Usar PROCEDURE en lugar de FUNCTION cuando sea posible.
Los procedimientos no escriben ni limpian el área de retorno, evitando gastar tiempo en algo qu no se va a tener en cuenta.

f) No usar AADD cuando el largo del array es conocido.
Si tenemos que crear un array y sabemos de que largo va a ser, no usemos AADD en forma recursiva o lineal para rellenar todo el array, en su lugar, creemos el array con ARRAY() y rellenemos sus datos con aArray[n].

g) En los IF complejos, escribir las opciones que más probabilidad tengan de definir en forma anticipada el resultado.
IF "condicion generlamente Verdadera" .and. "otra condicion"

es mejor hacer
IF "otra condicion" .and. "condicion generalmente Verdadera"

Seguramente habrá muchas formas más de optimizar el código con solo escribir un poco más ordenado.
Comments:
me habian comentado que Len en el for se evaluaba solo la primera vez. ¿Me equivoco?
 
Todo lo que esté tanto en TO como en STEP del FOR se evalua en cada iteración.

Observando el PCODE se puede ver que es asi:

FOR n:=1 TO Len(aArray)
NEXT

genera este PCODE

/*00*/ HB_P_BASELINE, 2, 0, /* 2 */
/*03*/ HB_P_ONE,
/*04*/ HB_P_POPVARIABLE, 1, 0, /* N */
/*07*/ HB_P_PUSHVARIABLE, 1, 0,/* N */
/*10*/ HB_P_PUSHSYMNEAR, 2, /* LEN */
/*12*/ HB_P_PUSHNIL,
/*13*/ HB_P_PUSHVARIABLE,3,0,/*AARRAY*/
/*16*/ HB_P_FUNCTIONSHORT, 1,
/*18*/ HB_P_LESSEQUAL,
/*19*/ HB_P_JUMPFALSENEAR, 13, /*13 (abs: 00032) */
/*21*/ HB_P_LINEOFFSET, 1, /* 3 */
/*23*/ HB_P_PUSHVARIABLE, 1, 0,/* N */
/*26*/ HB_P_INC,
/*27*/ HB_P_POPVARIABLE, 1, 0, /* N */
/*30*/ HB_P_JUMPNEAR, 233, /*-23 (abs: 00007) */
/*32*/ HB_P_ENDPROC
/*33*/

Explicacion:
N:=1 esta en las lineas 03 y 04

TO Len(aArray) que significa mientras que N <= Len(aArray) está en las lineas
07 a 19

el STEP 1 que es el valor por default, se encuentra en 23 a 27

el NEXT se encuentra en la linea 30, que salta a la linea 07.

Cuando la condicion ya no se cumple, salta a la linea 32, desde la linea 19

Por esto es que insisto tanto con el PCODE, porque entendiendolo, uno puede evaluar si ante un cambio el código es más optimo que el anterior.
 
Me abrumas, maestro.

El caso es que hace tiempo tuve esa idea de no poner el len en el for pero me dijeron que no se evaluaba mas que una vez. Creo que me lo dijo un individuo que programaba en "C" y allí es posible que si se evalue solo una vez.

Muchas gracias por deshacerme el entuerto.

Byte

OT.(Byte: Pequeño "adios" de informático inglés) :)
 
Muy interesante y didáctico.

Si ésto va a seguir así, creo que seré un habitual de este blog ;-)

Saludos
 
Paco,

en C y C++ también se evalúa en cada iteración. De hecho, la instrucción for(;;) de C se puede usar para cualquier tipo de bucles, no sólo bucles de contadores.

Si no me equivoco, es en pascal (lease Delphi) donde sólo se evalúa una vez.

Un saludo.
 
amigo, no entiendo lo de "Usar PROCEDURE en lugar de FUNCTION" a ver si entiendo bien: en lenguajes existen funciones (las cuales devuelven datos) y procedures que no lo hacen. en xharbour se cumple esta condición?

gracias
 
Publicar un comentario

<< Home

Powered by Blogger