Hola a todos:
Ya dije en el hilo del "otro proyecto" que sospechaba que SWITCH me estaba ralentizando el juego. Así que he decidido poner a prueba dicha teoría.
Adjunto el código de prueba, pero para el que sea tan vago de no descargarlo, os lo copio aquí:
program test_switch;
function mil_switch ()
private
int temp;
int cont;
begin
for (cont = 0; cont < 10000; cont++)
temp = rand(0,9);
switch (temp)
case 0..2: temp = temp; end
case 3..4: temp = temp; end
case 5..7: temp = temp; end
default: temp = temp; end
end //switch
end
end
function mil_switch2 ()
private
int temp;
int cont;
begin
for (cont = 0; cont < 10000; cont++)
temp = rand(0,9);
switch (temp)
case 0: temp = temp; end
case 1: temp = temp; end
case 2: temp = temp; end
case 3: temp = temp; end
case 4: temp = temp; end
case 5: temp = temp; end
case 6: temp = temp; end
case 7: temp = temp; end
case 8: temp = temp; end
case 9: temp = temp; end
end //switch
end
end
function mil_if ()
private
int temp;
int cont;
begin
for (cont = 0; cont < 10000; cont++)
temp = rand(0,9);
if (temp < 3) temp = temp;
elsif (temp < 5) temp = temp;
elsif (temp < temp = temp;
else temp = temp;
end
end
end
function mil_if2 ()
private
int temp;
int cont;
begin
for (cont = 0; cont < 10000; cont++)
temp = rand(0,9);
if (temp == 0) temp = temp;
elsif (temp == 1) temp = temp;
elsif (temp == 2) temp = temp;
elsif (temp == 3) temp = temp;
elsif (temp == 4) temp = temp;
elsif (temp == 5) temp = temp;
elsif (temp == 6) temp = temp;
elsif (temp == 7) temp = temp;
elsif (temp == temp = temp;
elsif (temp == 9) temp = temp;
else temp = temp;
end
end
end
BEGIN
set_mode(320,240,16);
set_fps(0,0);
write_int(0,10,10,0, &fps);
while (!key(_ESC))
//mil_switch2(); //215
//mil_if(); //280
//mil_if2(); //234
mil_switch(); //230
frame;
end
delete_text(all_text);
END
El código tiene 4 pruebas diferentes:
- mi_switch2: hace 10000 comprobaciones por frame. Obtiene un valor aleatorio entre 0 y 9, y usa un case diferente por cada valor, en donde hace una asignación en una variable (por hacer algo).
- mi_if: hace 10000 comprobaciones por frame. Obtiene un valor aleatorio entre 0 y 9, y usa cuatro comparaciones (if, elsif, elsif y else) en donde hace una asignación en una variable (por hacer algo).
- mi_if2: hace 10000 comprobaciones por frame. Obtiene un valor aleatorio entre 0 y 9, y usa un elsif diferente por cada valor, donde hace una asignación en una variable (por hacer algo).
- mi_switch: hace 10000 comprobaciones por frame. Obtiene un valor aleatorio entre 0 y 9, y usa 4 rangos de valores en el switch, en donde hace una asignación en una variable (por hacer algo).
Resultados en FPS:
- 215
- 280
- 234
- 230
Conclusiones: IF puede dar hasta un 20% más de velocidad que SWITCH en el mejor de los casos ¿Es porque hace menos comprobaciones? Probablemente, porque en el caso de los 10 posibles valores diferenciados, IF todavía da más velocidad, pero por poco.
Usar rangos de valores aumenta la velocidad del switch, pero aun así, usar elsif con valores individuales es ligeramente más rápido.
¿Cuándo usar uno u otro? en caso de problemas de rendimiento, siempre IF. SWITCH es mejor usarlo cuando queramos que el código sea fácilmente legible, o bien cuando queramos comparar con valores muy específicos, pero la mejor política es intentar agrupar todos los valores que vayan a desempeñar una función concreta.
Así que ahora me tocará tirarme unas cuantas tardes modificando el detector de tiles de durezas de los enemigos, sustituyendo los 200 switchs que hay por IF+OR, a ver si gano algo de rendimiento.
Y aquí concluye otro capítulo de "curiosidades internas de Bennu sin haberme leido el código fuente" :D
UPDATE:
He hecho un par de pruebas más, intentando seguir el código que estoy modificando para "el otro proyecto" y ¡horror! los resultados son peores.
Primero el cñodigo que he añadido a la prueba:
function mil_if3 ()
private
int temp;
int cont;
begin
for (cont = 0; cont < 10000; cont++)
temp = rand(0,9);
if (temp < 3) temp = temp;
elsif ((temp >= 3) && (temp < 5)) temp = temp;
elsif (((temp >= 5) && (temp < 8)) || (temp == 9)) temp = temp;
else temp = temp;
end
end
end
function mil_if4 ()
private
int temp;
int cont;
begin
for (cont = 0; cont < 10000; cont++)
temp = rand(0,9);
if ((temp == 0) || (temp == 1) || (temp == 2) || (temp == 3)) temp = temp;
elsif ((temp == 4) || (temp == 5) || (temp == 6) || (temp == 7) || (temp == 8)) temp = temp;
else temp = temp;
end
end
end
Los resultados en FPS han sido:
- mil_if3: 204
- mil_if4: 175
Definitivamente es algo que tiene que ver con las comprobaciones que se hacen internamente, los resultados obtenidos son mucho peores que con el switch, y eso significa que, previsiblemente, pierda rendimiento cuando acabe de escribir el nuevo código de comprobación de durezas. Voy a comprobarlo de todas formas, hice una copia de seguridad antes de hacer los cambios (por aquello que dije hace tiempo de volver atrás), así que no hay pegas.
lo vere... gracias!
Vale, he añadido un par de pruebas más que hice ayer, con resultados desastrosos. Desastrosos porque el código de prueba se parecen más al que estoy reescribiendo que lo otro, y la velocidad es mucho peor que los anteriores resultados.
Pero bueno, como digo, es sólo una prueba, siempre puedo volver atrás y hacer las cosas con más cabeza ^^U
PD: Tranquilo, Splinter, que esto no lo hago para buscar bugs en Bennu. Es simplemente para que la gente sepa qué es más rápido, por si desea optimizar sus códigos ;)
Revisando que hay de nuevo en bennu vi este tema...
Creo que tienes que hacer tus pruebas de nuevo, ya que los switch estan mal hechos, ninguno tiene el break, lo que significa que SIEMPRE va a ejecutar el caso en el que caiga primero y todos los de abajo.
Saludos
Quote from: Noivern on May 15, 2017, 05:09:53 AM
Revisando que hay de nuevo en bennu vi este tema...
Creo que tienes que hacer tus pruebas de nuevo, ya que los switch estan mal hechos, ninguno tiene el break, lo que significa que SIEMPRE va a ejecutar el caso en el que caiga primero y todos los de abajo.
Saludos
bennugd es un poco diferente a otros lenguajes, el end en cada case tiene un break implicito.