2010-05-17 6 views
7

J'ai commencé à travailler avec C# il y a quelques semaines et je suis maintenant dans une situation où j'ai besoin de construire un drapeau "bit set" pour gérer différents cas dans un algorithme. J'ai donc deux options:Amélioration significative des performances en utilisant des opérateurs au niveau du bit plutôt que des sommes entières en C#?

enum RelativePositioning 
    { 
     LEFT = 0, 
     RIGHT = 1, 
     BOTTOM = 2, 
     TOP = 3, 
     FRONT = 4, 
     BACK = 5 
    } 

    pos = ((eye.X < minCorner.X ? 1 : 0) << (int) RelativePositioning.LEFT) 
     + ((eye.X > maxCorner.X ? 1 : 0) << (int) RelativePositioning.RIGHT) 
     + ((eye.Y < minCorner.Y ? 1 : 0) << (int) RelativePositioning.BOTTOM) 
     + ((eye.Y > maxCorner.Y ? 1 : 0) << (int) RelativePositioning.TOP) 
     + ((eye.Z < minCorner.Z ? 1 : 0) << (int) RelativePositioning.FRONT) 
     + ((eye.Z > maxCorner.Z ? 1 : 0) << (int) RelativePositioning.BACK); 

Ou:

enum RelativePositioning 
    { 
     LEFT = 1, 
     RIGHT = 2, 
     BOTTOM = 4, 
     TOP = 8, 
     FRONT = 16, 
     BACK = 32 
    } 

    if (eye.X < minCorner.X) { pos += (int) RelativePositioning.LEFT; } 
    if (eye.X > maxCorner.X) { pos += (int) RelativePositioning.RIGHT; } 
    if (eye.Y < minCorner.Y) { pos += (int) RelativePositioning.BOTTOM; } 
    if (eye.Y > maxCorner.Y) { pos += (int) RelativePositioning.TOP; } 
    if (eye.Z > maxCorner.Z) { pos += (int) RelativePositioning.FRONT; } 
    if (eye.Z < minCorner.Z) { pos += (int) RelativePositioning.BACK; } 

Je aurais pu utiliser quelque chose comme ((eye.X > maxCorner.X) << 1) mais C# ne permet pas de coulée implicite bool int et l'opérateur ternaire était assez similaire. Ma question est la suivante: y a-t-il une amélioration des performances en utilisant la première version au cours de la seconde?

Merci
Tommaso

+8

avant d'effectuer des micro optimisations –

+0

D'accord avec Mitch Wheat. Préférez également la lisibilité plutôt que la performance, sauf si vous pouvez prouver un goulot d'étranglement avec un profileur. – OregonGhost

+4

"Nous devrions oublier les petites efficacités, disons environ 97% du temps: l'optimisation prématurée est la racine de tout mal" Donald Knuth – Cagdas

Répondre

5

L'opérateur en ligne if (?, :) va générer à peu près la même IL que la liste if standard dans le second exemple. La seule différence que vous verrez ici sont les opérations particulières que le processeur va faire, et je peux parier que ADD est plus rapide que SHL.
Puisque vous allez ajouter les résultats de toute façon, j'opterais pour le second exemple (en plus cela rend la lecture beaucoup plus facile).

EDIT
Je viens de vérifier l'IL des deux exemples, et il va à l'encontre de ce que je l'ai dit ci-dessus.
Le premier exemple génère beaucoup moins d'IL (34 lignes de moins), donc vous devrez exécuter un test de performance pour déterminer si c'est aussi plus rapide.

+0

+1 pour l'édition. –

0

Significativement plus rapide? non. Légèrement plus rapide? Un petit peu.

8

Vous devez absolument utiliser le Flags attribute pour votre énumération. De cette façon, il ressemblerait à quelque chose comme ça:

[Flags] 
public enum RelativePositionings 
{ 
    None = 0, 
    Left = 1, 
    Right = 2, 
    Bottom = 4, 
    Top = 8, 
    Front = 16, 
    Back = 32 
} 

Avec cela, vous pouvez faire des choses comme:

var position = RelativePositionings.Left | RelativePositionings.Front; 

et vérifier pour chaque état par:

if(position.HasFlag(RelativePositioning.Left)) 
{ 
    //To do: if left bit is set? 
} 
référence
Questions connexes