optimiser les calculs d'entiers avec les opérations sur les bits
traduction de l'article: http://lab.polygonal.de/2007/05/10/bitwise-gems-fast-integer-math/
Les opérateurs bitwise sont très rapides en AS3, alors voilà une petite collection d'optimisations de calculs. Je n'expliquerai pas ce que sont les opérateurs de bits et comment s'en servir, je préfère linker un excellent article hébergé sur gamedev.net: ‘Bitwise Operations in C’.
Si vous connaissez d'autres astuces qui ne sont pas listées ici, vous pouvez les ajouter par commentaires. Tous les tests de rapidité ont été faits en AS3.
Environ 300% plus rapide.
x = x * 2;
x = x * 64;
//equivaut à:
x = x << 1;
x = x << 6;
Environ 350% plus rapide.
x = x / 2;
x = x / 64;
//équivaut à:
x = x >> 1;
x = x >> 6;
reste = numérateur & (diviseur - 1);
C'est environ 600% plus rapide.
x = 131 % 4;
//équivaut à:
x = 131 & (4 - 1);
Pas vraiment une astuce, la méthode régulière pour consulter les canaux rouge vert bleu alpha.
//24bit
var color:uint = 0x336699;
var r:uint = color >> 16;
var g:uint = color >> 8 & 0xFF;
var b:uint = color & 0xFF;
//32bit
var color:uint = 0xff336699;
var a:uint = color >>> 24;
var r:uint = color >>> 16 & 0xFF;
var g:uint = color >>> 8 & 0xFF;
var b:uint = color & 0xFF;
Décaler les valeurs aux bonnes positions et les combiner avec l'operateur bit or ( | ).
//24bit
var r:uint = 0x33;
var g:uint = 0x66;
var b:uint = 0x99;
var color:uint = r << 16 | g << 8 | b;
//32bit
var a:uint = 0xff;
var r:uint = 0x33;
var g:uint = 0x66;
var b:uint = 0x99;
var color:uint = a << 24 | r << 16 | g << 8 | b;
20% plus rapide
var t:int = a;
a = b;
b = t;
//équivaut à:
a ^= b;
b ^= a;
a ^= b;
Etrangement c'est 300%(!) plus rapide.
i = -i;
//équivaut à
i = ~i + 1;
//ou
i = (i ^ -1) + 1;
C'est 600% plus rapide.
pair = ((i % 2) == 0) ;
//équivaut à:
pair = ((i & 1) == 0) ;
Oubliez Math.abs() pour le code critique en consommation cpu. La version 1 est 2500% plus rapide que Math.abs(), et la version version 2 est encore 20% plus rapide que la version 1.
//version 1
i = x < 0 ? -x : x;
//version 2
i = (x ^ (x >> 31)) - (x >> 31);
C'est 35% plus rapide.
memeSigne = (a * b > 0);
//équivaut à:
memeSigne = (a ^ b >= 0);
R8 = (R5 << 3) | (R5 >> 2)
G8 = (R5 << 3) | (R5 >> 2)
B8 = (R5 << 3) | (R5 >> 2)
Rajout personnel, astuce découverte après étude d'un classique en open-source:
Appliquer la rapidité des integers à des nombres décimaux
Il suffit pour cela d'encoder les nombres décimaux sur des integer de 32 bit.
Par exemple, on prend 16 bits pour coder la partie entière et 16 bits restants pour la partie décimale.
Très utile pour encoder des maps vectorielles 2d ou 3d sans utiliser de float.
Les calculs d'affichage et de collision reposant intégralement sur l'encodage des points, le gain de vitesse est très significatif (calculs avec integer 300% plus rapides qu'avec float).
Pour convertir le nombre décimal 64bit en pseudo-décimal 32bit:
intDecimal = int( floatDecimal * ( 1 << 16 ) )
Pour retrouver la valeur décimale une fois les calculs effectués:
floatDecimal = intDecimal / ( 1 << 16 )