domingo, 3 de abril de 2016

Laboratorio rendimiento If vs Switch en Visual Studio C#.

Laboratorio rendimiento If vs Switch en Visual Studio C#.

Buenas a todos espero que la semana santa les haya dado un buen descanso y nuevos aires para continuar haciendo lo que nos apasiona.

Desde hace mucho tiempo, a nivel de programación surgen muchas preguntas a medida que se va avanzando en este mundo; de mi memoria unas de las preguntas que me he realizado y aun me sigo haciendo, es la siguiente, “Que es mas optimo o rápido en la toma de decisión un If anidado o un switch”, pues creanlo o no aun no tengo una respuesta para ello y cada vez que trato de dar una respuesta se amplían más las posibilidades y las variables; me acuerdo, echando memoria muuuyyy atrás en mis tiempos de universidad en clases de circuitos, el profesor que ni me acuerdo ya de él, pero sí de su asistente (bueno no se si era asistente o docente ya en ese tiempo) Eva !hayy donde carajos estará esa muchacha¡, bueno y su hermana también (como tema aparte estas dos muchachas eran por decirlo de alguna forma unas nerdas, pero bien bonitas, ojala sigan asi, ahora entiendo del porque no me concentraba en las clases), en fin, el profesor decía que a nivel de circuitos es mas optimo y rápido las compuertas and-or que usar un PIC y programarlo como una instrucción de control switch, pues uno aquí en que le alega al profe, ps nada, no hay mucha forma, primero, porque programar ese PIC ya es todo un cuento (aclaro que mi fuerte no es la electrónica, más bien la locha :)).

Ahora mirando el problema desde el punto de la programación de software, ps ya entran un poco de variables como por ejemplo, el lenguaje de programación y el entorno en donde se ejecuta el programa en sí, no más con esto, ya tienes un montón de posibilidades para probar; para centrarnos un poco, este laboratorio lo realizaremos con .NET y C#; divagando un poco por la información que he leído y en el momento que escribo este post, vienen los flashes de retazos de información, hay algo que recuerdo, y fue algo que leí hace ya mucho rato, hay un tipo, obviamente alguien que sabía o sabe programar que escribió sobre lo mismo (lamentablemente no tengo el enlace y no me acuerdo del nombre del sujeto en cuestión), este personaje, si no mal recuerdo mencionaba que la sentencia switch es mas optima, ya que el compilador la optimiza con tablas de saltos (jump tables), que en si, es una mejora de rendimiento a la hora de ejecutar partes del código fuentes especificas, algo que nos puede hacer plantear la siguiente hipotesis “el uso de switch es más optimo que sentencias if anidadas, por el uso de la tabla de saltos”. 

Hay un post, que aun guardo la url y me gusto, debido a que comenta que dependiendo del caso (mirando a nivel lógico, se ve que lo descrito es más que acertado) es mejor usar los if anidados en vez del switch y para otros casos en mejor usar el switch en vez de los if anidados, aqui dejo el link para que lo miren.

Para este laboratoria, diseñaremos un programa Windows Form, para hacer la simulación del objetivo que nos compete, mientras estoy escribiendo debo decirles que no tengo nada hecho y voy hacer el programa sobre la marcha el programa, mejor dicho vamos hacer de científicos de a prueba y error y ejecutaremos las ideas que vengan de la inspiración del viento, jejeje si asi es.

Se definirá el programa como sigue (se que cambiara a medida que lo vamos codificando y con las  diferentes ideas que se nos ocurran, pero empezaremos marcando una línea partida). Existirán dos métodos, uno para el caso del switch y el otro para el caso del if anidado. Tanto el if como el switch constaran de 10 casos a ser validados (comparaciones simples del 1 al 10).

Cada método se ejecutará en un ciclo, el cual se puede definir en un archivo de configuración o en el programa (lo del ciclo es como para emular el dato de una media ponderada en cuanto a tiempo).

El programa en si se basara en la medición del tiempo en ejecución de la sección switch y la sección if, hay que tener en claro que juegan muchos factores en contra para realizar el laboratorio, la idea es que solo el procesador del pc le dedicará el 100% de su procesamiento para que de unos resultados más reales, sabemos que esto no es posible ya que el procesador va ejecutar muchas operaciones algunas de mayor prioridad que otras, y se demorará en procesar según el número de procesos (valga la redundancia) que esté ejecutando en el momento, para bajar un poco el grado de esta limitante al ejecutar el programa abriremos el administrador de tareas (sistemas windows) y le subiremos la prioridad a Alta cuando realicemos la simulación.

Ahora entrando a parte técnica, nos planteamos primero como tomar el tiempo de ejecución, en .NET existe una clase optimizada para dicho propósito, esta clase es Stopwatch, con esta clase podemos medir el tiempo trascurrio desde cierta parte del código que queramos y su funcionamiento es sencillo, solo es iniciar una variable donde queremos que se empiece a contabilizar el tiempo y parar ese conteo en donde queramos que finalice el conteo (nuevamente valga la redundancia), algo como la siguiente imagen. 


Hay mucha información en la sobre este tem, de cómo medir el tiempo de ejecución. 

Antes de continuar, a la aplicación le agregaremos la siguiente prueba, debido a algo que surgió de momento. 
  • Se agregara método para manejar el caso de if-else anidados. 
Tendremos entonces tres mediciones, uno para el if (en espagueti, solo if), el if else anidados, y el switch, más que válido el agregar el último caso. 

El código de la aplicación lo manejaremos en GitLab (seeeee !!!!), al fin voy a subir alguito, esto me acuerda de algo, vamos hacer un post sobre como manejar Git, se que he subido dos post pero hacen más referencia a los servicios de GitLab y GitHub que a la filosofía del control de versiones GIT, haremos algo básico, básico para no morir en el intento :).

bueno creo que tenemos un panorama de lo que vamos hacer, así que manos a la obra……… 

Hemos finalizado la app que realizara el laboratorio, poner aqui una funcion solamente, el código completo lo puedes visualizar o descargar de aqui el proyecto esta en la carpeta LabVS.

Método VerIf. 
private bool VerIf(int v)
{
  bool res = false;
  if (v == 1)
  {
     res = true;
  }
  if (v == 2)
  {
     res = true;
  } 
   ........

  if (v == 10)
  {
     res = true;
  }
  return res;
} 

Imagen 2

La imagen 2, es como vamos a ejecutar cada función para tomar un tiempo de ejecución del ciclo total, primero se iniciará el temporizador, luego pasará el ciclo que ejecutará la función n veces, al finalizar el ciclo paramos el temporizador, la idea no es medir cuánto se demora en un if, si no que vamos a ejecutar varias veces la misma función para tener un tiempo total y comparar ese tiempo en los tres caso, de esta forma miramos cual de el menor tiempo; ¿porque vamos a  usar un número alto de ciclos? es debido a que el procesador ejecuta la tarea en nanosegundos y queremos ampliar este tiempo para que sea más perceptible por nosotros.

Como lo comentamos arriba, vamos aumentar la prioridad de la aplicación de laboratorio y cada función la vamos a ejecutar un número de veces, este número de veces será un número elevado, un ciclo de 2000000 iteraciones (elevado para hacerlo nosotros. el pc vuela).

Esta será la IU de la aplicación, hay algunas cosas que explicaremos de ella.

Imagen 3

Bueno esta super interfaz, funciona así, valor, es el número a comparar, iteraciones, es el número de veces que se repetirá el ciclo, el campo de selección (switch, if, if_else), es para seleccionar qué método ejecutar, en TSwitch, TIf, TIfElse, es donde se mostrará el tiempo al finalizar la ejecución, el botón Ejecutar es para cuando se va ejecutar una sola opción, el botón EjecutarTod es para ejecutar los tres casos, no al tiempo si no para que nos arroje el resultado de los tres casos, creo que nos queda claro (??????????). 

Describiré los equipos donde se ejecutará la prueba 

PC1

PC2

PC1 es un poco mas actual, creo que del 2014, PC2 es de a principios 2011, en cada uno ejecutaremos 5 veces el laboratorio y compararemos el resultado, vamos a comparar el número 8 para que haga unas cuantas verificaciones antes de que se encuentre el if o case correcto y solo ejecutaremos con el laboratorio con el botón EjecutarTod, tambien vamos a ejecutar el programa desde el binario no desde el visual studio ya que esto puede hacer retrasar el proceso y la lógica de funcionamiento normal del procesador.

Como subir de prioridad al programa 

primero ejecutamos la aplicación que está en el directorio bin del proyecto (claro primero se compila) 
luego abrimos el administrador de tareas, y buscamos el programas. 



Luego damos clic derecho y escojemos la opción Ir a Detalles.


Nuevamente clic derecho en el programa y seleccionamos la opción Establecer Prioridad y seleccionamos Alta. 


Saldrá una ventana de advertencia y seleccionamos cambiar prioridad. 


Listo ya tenemos configurado el programa, ahora si a ejecutar el laboratorio.

Capturas de resultado en PC1

Imagen 
Imagen 
  
Imagen 
  
Imagen 
  
Imagen 
  

Captura de resultados PC 2 

Imagen 
Imagen 
Imagen 
Imagen 
Imagen 
  

Tabla de Datos 

Imagen

Con esto podemos dar un resultado, pero para lavarme las manos lo haré a nivel personal ustedes ya decidieron que concluir, el porqué de esto, pues fácil, se me salen de las manos la infinidad de variables a manejar y cualquier cosa más que en sus cabezas llenas de sabiduría ronda y que pueden ser muy validadas.

Según los resultado, y teniendo en cuenta que se usó el Framework .Net para el desarrollo de la aplicación de laboratorio, en visual studio si viene optimizada la sentencia switch (bueno hasta el momento ya saben la tecnología es muy variable, año 2016, jeje).
  • El uso de Switch para comparaciones simple y que tengan varias posibilidades es más rápido, que el uso de if y if else anidados (teniendo en cuenta que no evaluamos un caso para un valor inicial como el número 2).
  • En ese mismo caso la sentencia if else anidada es un poco mas rapida que la if. 
  • Que la arquitectura de procesador si importa a la hora de velocidad de cómputo, :), eso lo sabemos pero aquí se comprueba otra vez. 
Generalmente eso, falta mucho para afinar este laboratorio, pero si hago un par de casos más se alargaría tanto este tema que me tocaría que desplazar muchas cosas personales que tengo que hacer y eso que ya llevo desarrollando este post por más de dos semanas. 

Te reto a que hagas algunos caso como: 
  • Tomar el valor 2 con el mismo número de ciclos, para ver qué resultados se obtiene. 
  • Que pasa si aumentamos el número de ciclos a 4000000. 
  • Probar en una arquitectura AMD.

Si ven, salen muchas posibilidades y casos interesantes, me surgieron varias preguntas, no solo sobre el tema en cuestión de switch o if, sino a nivel de rendimiento de procesamiento, comparaciones, se me ocurrió una idea para un proyecto y es crear un programa para estadísticas de procesamiento de un computador, tengo muchas cosas por hacer, si tambien incluyo jugar wow en ellas por eso si alguien quiere trabajar en dicho programa, pues nos contactamos para desarrollar algo divertido y funcional.

Por el momento me despido, y feliz laboratorio.

@drincast

No hay comentarios: