Optimization de code pour du Xna rapide et efficace !

Je dois en omettre un grand nombre, si vous en avez d’autres n’hesitez pas à me les soumettre que je les rajoute ici !

Première optimisation, les strings :

Eviter tout indexeur à base de string s’il y’a un équivalent à base d’int.

L’instruction :

myEffect.Techniques[“Precompiled”] ;

Est bien moins efficace q’un :

const int TechnikIndex = 0;

myEffect.Technique[TechnikIndex]

Eviter au maximum la class string, si on a besoin de puissance. En C# tout modification d’une string entraine la création d’une nouvelle instance et donc une allocation mémoire. Une string N EST JAMAIS MODIFIABLE et l’allocation mémoire est une opération très couteuse en temps. Il faut donc travailler un maximum avec StringBuilder.

 Besoin de comprendre le string intern pool. Quand on créé une string, le clr regarde dans un pool interne si elle existe avant de la créer. (méthode statique Intern de la classe string).

Donc string jamais collectés comme les objets communs dans le GC.

 

 Boxing/unboxing

Boxing passage d’un value type (exemple int) à une classe objet .

Par exemple :

int a  = 0;

object o = (object)a;

Unboxing est l’opération inverse.

boxed = 20 fois plus de traitement CPU qu’une simple affectation de ref

unboxed = 4 fois plus

= généric autant que faire se peux (optimization en Early binding)

 Pour les struct, implementer la méthode ToString (sinon il y’a boxing en objet pour chaque appel à cette méthode)

 

Array

Jagged Arrays > Rectangular Array ([][] > [,])

Privilegier les for au foreach (moins nécessaire depuis le .Net 3.0)

addrange plutot que add

Range Check important, exemple :

//rapide
for(int i = 0; i < myArray.Length; i++)
{
   Console.WriteLine(myArray[ i ].ToString());
}
//plus lent
for(int i = 0; i < myArray.Length + y; i++)

   Console.WriteLine(myArray[ i+x ].ToString());
}

Dans la seconde boucle le test ne porte pas sur la longueur du tableau traité mais sur une autre valeur, il y’a donc des tests supplémentaire ajouté en IL pour générer une exception en cas de sortir de Bounds.

Methodes :

Il y’a quelque regles simples pour que le compilateur utilise de l’inlined (suppresion à la compilation d’une méthode pour inclure son code en lieu et place de l’instruction appellant la dite méthode) :

  • 32o d’il (8instructions) max par méthode/accesseur/mutateur à “inliner”
  • pas de structures conditionnelles dans le bloc à inliner
  • pas de type struct utilisé dans le bloc à inliner
  • pas de bloc Try/Catch/Finaly dans le bloc à inliner.

Si il n’y a pas besoin de rendre le code compréhensible on priviligiera les chunky call au maximum (méthodes énormes en lieu et place de myriades de petites méthodes qui s’appellent les unes les autres).

 

Thread

Synchroniser les thread : System.Threading.Interlocked class

 

 Exception

retourner des enum plutot que des exception sur les méthodes critiques

Eviter ce genre de code :

public static void Main(string[] args){
  int j = 0;
  for(int i = 0; i < 10000; i++){
    try{   
      j = i;
      throw new System.Exception();
    } catch {}
  }
}

En asp.net, à eviter :

L’instruction : Response.Redirect() elle provoque un ThreadAbortException

Un throw d’exception perturbe gravement l’activité CPU associée à votre applicatif.

 

Objets

Utiliser au maximum les structure là ou la notion de référence n’est pas importante (besoin ponctuelle d’agrégat ordonné de données) en lieu et place d’une class

(Exemple de la structure Point, Rectangle, etc.) . La gestion en mémoire est alors bien plus efficace et rapide.

Apprecier au maximum l’attribut Fieldoffset qui permet de réaliser l’équivalent de l’Union du langage C pour optimiser la mémoire

Utiliser les weakreference notamment pour le cache, afin de ne pas surcharger la mémoire.

 

 Framework :

Working Set : charger une assembly pour profiter d’une seule de ses méthodes c’est pas bien !

Utiliser vadump.exe pour détecter ca dans son framework

Se servir de Perfmon et de ses attributs (nb de classes chargées, nombre de méthodes, temps passé à loader, JITed, etc.)

 

 Executables :

Précompilation avec ngen.exe pour les exes critiques. Permet de précompiler son application pour un premier lancement rapide.

 

SQL 

connexion ouverte longtemps < multiple ouverture /fermeture de connexion

Datareader > dataset

Annuler le transaction enlistment si inutile

 SqlConnection conn = new SqlConnection(

“Server=exasrv01;

Integrated Security=true;

Enlist=false”);

10 thoughts on “Optimization de code pour du Xna rapide et efficace !”

  1. Article interessant !

    Cependant, j’ai une question en rapport avec l’opération de boxing et unboxing.

    Imaginons une texture où nous mettons 5 tiles, nous aurons donc un tableau de rectangles de ce style :

    Rectangle[] rc = new Rectangle[5]
    {
    new Rectangle(0, 0, 100, 50),
    new Rectangle(0, 51, 100, 50),
    new Rectangle(0, 102, 100, 50),
    new Rectangle(0, 153, 100, 50),
    new Rectangle(0, 204, 100, 50)
    };

    Ainsi pour avoir le premier élément de la liste, on mettrait 0 comme index. Cependant, si le programmeur ne veut pas regarder perpetuellement plusieurs lignes au dessus de son code pour savoir que l’indice 0 correspond au bouton A, 1 au bouton B, etc…, il serait tenter de créer une énumération comme ceci :

    enum GameButton : int
    {
    A = 0,
    B,
    X,
    Y,
    Start
    }

    et ainsi il écrirait ceci :

    public void DrawButton(GameButton but)
    {
    spriteBatch.Draw(texture, position, rc[(int)but], …);
    }

    Maintenant la question que je pose est :

    Comment se fait-ce qu’une énum qui est pourtant considérée en int, doit avoir un castage et est-ce qu’il est aussi coûteux qu’un cast int en obj ou obj en int et autres ?

    Sinon quand vous parlez de généricité, est-ce que vous parler de l’utilisation d’un truc du style :

    public T ConvertToEnum(string value)
    {
    return (T)Enum.Parse(typeof(T), value, true);
    }

    En vous remerciant …

  2. L’énum est un value type à part entière créé par le développeur. Ce n’est donc pas sémantiquement parlant un int, short, byte etc.
    Les valeurs d’une énum ne sont pas 0, 1, 2, 3, … mais A, B, C, D. On peut faire une correlation avec le type char, ‘A’ n’est pas un int, mais on sait très bien qu’il équivaut à une valeur entière coté ASCII.
    Le compilateur heureusement est au courrant de ça et manipule ce genre de cast en amont. Ce qui fait que écrire rc[(int)but] ou rc[0] est aussi rapide.

  3. Bonjour,

    J’ai récement découvert dans un projet C# qu’il était possible de faire des goto en C#. Dans aucun livre traitant de C#, aucun tuto ou cours en ligne, et jusqu’a aujourd’hui, dans aucune source je ne l’avais rencontré. Donc je me suis demandé si il étatit plus performant de faire un goto ou un while pour une boucle ? Et voici ce que j’ai obtenu en IL :

    Label:
    goto Label;

    IL_0000: nop
    IL_0001: br.s IL_0001

    while(true) {}

    IL_0000: nop
    IL_0001: br.s IL_0005
    IL_0003: nop
    IL_0004: nop
    IL_0005: ldc.i4.1
    IL_0006: stloc.0
    IL_0007: br.s IL_0003

    Je ne connais pas bien l’IL, mais a vu de nez, je dirais qu’il faudrait privilégier le goto. Mais alors pourquoi n’en parle-t-on presque pas ? Est-ce considéré comme mauvais pour la lisibilité du code, et donc comme une mauvaise pratique ? Est-ce une source d’erreur difficilement débugable trop importante ? Est-ce que le gain de performance est négligeable ?

    Et qu’est ce qui éxplique cette différence d’IL pour un résultat identique ?

    Merci.

  4. En fait si on ne priviligie pas le Goto ce n’est pas une question de performances mais plutot une question de lisibilité du code.
    Les detracteurs de cette intruction invoque la difficile maintenance d’un code comportant un grand nombre d’étiquette.
    Le goto n’est pas une intruction lente.
    Moi même qui aime bien le code propre et lisible je l’utilise quelque fois dans des cas bien particuliers. Par exemple pour sortir de plusieurs imbrications de boucles ou dans des switch importants. C’est aussi une instrction qui permet l’inlining.

  5. Wow. Je viens d’apprendre un tas de trucs dans cet article. Est ce que je peux en reprendre quelques uns pour mon site (l’idée hein, je ne me permettrai pas de voler le contenu tel quel) ?

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>