Posté le: 17/09/07 23:00 Sujet du message: Mon avis sur les "memory leak" - à méditer
Mon but n'est pas de lancer un débat sur les fuites de mémoire, mais simplement d'ouvrir les yeux sur quelques réalités.
1) Qu'est ce qu'une fuite de mémoire (memory leak) ?
Comme la majorité d'entre vous le savent surement déjà, la mémoire vive de votre ordinateur est utilisé par vos programmes pour effectuer leurs tâches.
Wacraft3 n'échappe pas à la règle, et dans vos parties, lorsque vous créez une unité, un arbre, un effet spécial, un buff, ou même lorsque vous utilisez des points (locations), des groupes d'unités, etc... dans vos triggers, cela "consomme" de la mémoire.
Chaque type "d'objet" consomme plus ou moins de mémoire vive, très peu en général.
Mais un problème survient lorsque l'on utilise dans nos triggers certains "objets" (location, groupes, ...) qui sont créés mais jamais supprimés utilisant alors de la mémoire pour rien jusqu'a la fermeture de la map ; on observe alors une "fuite de mémoire".
2) Comment y remédier ?
Le principe est simple : stocker dans une variable l'objet voulu, l'utiliser dans notre déclencheur, puis enfin le supprimer (je rappelle que le terme "d'objet" inclue toutes les "choses" pouvant être créées dans warcraft3, ceci inclue les textes affichés à l'écran, les sons, et plein d'autres choses qu'on ne soupçonnerait même pas...)
La solution la plus simple est d'utiliser le jass et des variables locales, mais certaines astuces permettent de le faire en GUI aussi.
Prenons l'exemple suivant : nous voulons créer une unité au centre d'une région (le centre de la map dans notre cas), le trigger habituel serait :
Gui:
Trigger:
Creation unite Evénements Conditions
Actions
Unité - Create 1 Fantassin for Joueur 1 (Rouge) at (Center of (Playable map area)) facing Orientation bâtiment par défaut degrees
La fonction (Center of (Playable map area)) qui calcule le centre de la région renvoie un point (x,y,z) ou "location" en anglais.
Ce déclencheur "leak" (fuit) car la location est créée mais jamais supprimée.
La solution serait de faire ceci :
Gui:
Trigger:
Creation unite sans leak Evénements Conditions
Actions
Set Mon_point = (Center of (Playable map area)) Unité - Create 1 Fantassin for Joueur 1 (Rouge) at Mon_point facing Orientation bâtiment par défaut degrees Custom script: call RemoveLocation( udg_Mon_Point )
La dernière ligne est une ligne de Jass, mise dans un custom script, car la fonction qui supprime un point n'existe malheureusement pas en GUI.
On pourrait encore rajouter une ligne de jass ( set udg_Mon_Point = null ) pour règler complètement le leak, mais ne compliquons pas les choses.
Vous avez compris le principe.
3) Le leak, d'accord, mais est-ce si grave que cela ?
Oui et non.
Pour les initiés, il faut savoir qu'un objet ne fuit que de quelques octets, voir quelques dizaines tout au plus pour certains, et votre ordinateur en possède plusieurs milliards ; bien entendu, beaucoup sont déjà utilisé par votre système d'exploitation (windows, linux, mac OS, etc...), par les autres programmes en cours d'exécution et par le processeur en lui même qui en réquisitionne une partie pour ses calculs.
On en viendrait donc à dire que ce n'est donc pas grave du tout, mais à vrai dire, tout dépend de votre map.
Vous avez peut être déjà remarqué dans certains vieux TD (Tower Defense), que la map devenait injouable au bout de 40minutes, voir une heure de jeu, à cause du lag ?
Ceci était surement dû à des "memory leak", car énormément d'unités sont créées sur cettes map et très souvent, ce qui entraînait des très nombreux leak sur des points (qui en eux même ne doivent utiliser que quelques octets (3 coordonées, donc 3 réels, 4octets par réels, ce qui nous donne donc 12 octets normalement)).
Le cumul de tous ces leak, finissaient par utiliser toute votre RAM disponible et faisaient lagger votre PC.
Malgrès tout, je pense qu'il est aussi nécessaire de prendre en compte l'évolution des PC actuels : de plus en plus de gens ont maintenant 1 voir 2Go de RAM sur leur PC, ce qui augmente énormément la marge de "leak" acceptable, ce qui minimise ses conséquences.
Les effets du leak sont quasi inexistant sur les pc moderne.
Petite note interessante, plus la map a utilisé de mémoire pendant la partie, plus l'écran noir quand on la quitte est long, car c'est à ce moment que la mémoire est libérée.
4) C'est de la folie, le leak j'en entend parler tout le temps !
Parce que tout le monde n'a pas un PC de roXXor avec 2Go de RAM, de plus, par habitude et pour faire les choses "correctement", il est bien de coder sans leak.
Néamoins, je trouve cela ridicule de se focaliser sur le leak comme source de lag en partie, car je pense (et j'ai la certitude) que la plus grande majorité du lag provient de la manière dont les maps sont codées (sans tenir compte des leak).
Je m'explique.
Les évènements périodiques, les compteurs (timers), et autres boucles inutiles sont d'autant plus de sources de ralentissements et même un leak, pourrait être amoindri en étant un peu futé.
Par exemple, on veut créer deux unités différentes au centre d'une région :
Gui:
Trigger:
Chevalier et fantassin Evénements Conditions
Actions
Unité - Create 1 Fantassin for Joueur 1 (Rouge) at (Center of (Playable map area)) facing Orientation bâtiment par défaut degrees Unité - Create 1 Chevalier for Joueur 1 (Rouge) at (Center of (Playable map area)) facing Orientation bâtiment par défaut degrees
Ce déclencheur leak deux fois, une location par action.
Maintenant, sans supprimer le leak, nous pourrions le minimiser comme ceci :
Gui:
Trigger:
Déclencheur sans titre 009 Copier Evénements Conditions
Actions
Set Mon_point = (Center of (Playable map area)) Unité - Create 1 Fantassin for Joueur 1 (Rouge) at Mon_point facing Orientation bâtiment par défaut degrees Unité - Create 1 Chevalier for Joueur 1 (Rouge) at Mon_point facing Orientation bâtiment par défaut degrees
Ce déclencheur ne leak plus qu'une seule fois.
Ceci n'était qu'un exemple d'optimisation, mais je trouve que la priorité serait donc plutôt d'apprendre à "coder correctement" : utiliser les bons évènements (le moins possible de périodiques) notamment, bien avant même de penser à règler les leak qui ne sont que l'étape ultime de l'optimisation de la map.
Car une map sans leak mal conçue (évènements périodiques et des timers en pagaille par exemple) aura toujours de gros problèmes.
Le gros du travail pour des systèmes assez lourd, est également de minimiser au maximum les calculs mathématique (factoriser, éviter les fonctions "lentes", etc...)
5) Conclusion
Ne pas crier "au loup" et se focaliser sur le "leak", mais plutôt apprendre ses évènements afin de mieux les utiliser, et réfléchir à la manière la plus simple (le moins de calcul possible) pour arriver à ce que l'on veut faire, et si besoin, demander conseil sur la méthode à utiliser ici même sur le forum.
Il est fait pour cela, et des posts "débats" pour partager nos méthodes et nos conseils ont aussi leurs place dans le forum déclencheurs
J'espère que ce post aura éclairé certains sur les raisons de ma "prise de position" au sujet des leaks de ces derniers jours, et d'autres sur la nature même et les conséquences des leak.
~profet _________________
Dernière édition par profet le 26/02/09 00:52; édité 6 fois
Si vous avez des questions, n'hésitez pas à les poser dans ce sujet, je metterai à jour ce post pour y créer une FAQ.
Pourquoi faut-il nullifier les variables locales en fin de fonction ?
Pendant longtemps le débat a été mis sur le devant de la scène, mais c'est un fait avéré, ne pas nullifier une variable locale en fin de fonction leak.
Anitarf a écrit:
Because local pointers aren't cleared at end of function, they remain in memory if you do not set them to null, causing a minor leak, just a few bytes per pointer.
Pour les non anglophones, cela dit:
Parce que les pointeurs locaux (variables locales) ne sont pas "nettoyés" en fin de fonction, ils restent en mémoire si vous ne les nullifiez pas , entrainant une fuite mineure, juste quelques octets par pointeur.
Citation:
A handle can only be recycled if the object stored there is destroyed and there are no pointers pointing to it.
Here is the catch. When you allow a pointer to stay in memory, it does not only take up those few bytes by itself, it also prevents a handle from being recycled, which is a lot more critical.
Une handle (=identifiant d'une entité/objet de war3) ne peut être recyclée que si l'objet stocké (en mémoire) est détruit, et si aucun pointeurs ne pointent encore dessus. Quand vous laissez un pointeur rester en mémoire, il ne fait pas qu'utiliser ces quelques octets, il empêche aussi la handle d'être recyclée, ce qui est plus problématique. _________________
Bêta Systems:70% Bêta Spells:13% Bêta Arts & graphics:70%
Dernière édition par profet le 19/07/09 02:12; édité 2 fois
Inscrit le: 21 Aoû 2007 Messages: 915 Sujets: 47 Spécialité en worldedit: Faire des maps avec 500 déclos en GUI alors que 2 en JASS suffisent Médailles: 1 (En savoir plus...)
Posté le: 21/09/07 18:11 Sujet du message:
Îl faudrais mettre un lien a ce tuto dans la partie des tutos, c'est un tuto apres tout ^^
EDIT de profet: pas vraiment car il n'explique pas vraiment une méthode pour règler un problème _________________
les leak saylemal, que monsieur profet le veuille ou non
J'ai jamais dit le le leak etait bien, je code sans laisser aucun leak possible, j'essaie simplement de faire comprendre aux gens, qu'avant de vouloir règler les leak, il vaut mieux apprendre à coder de la bonne manière car bien souvent les problèmes de lag ne viennent pas des leak... _________________
Bêta Systems:70% Bêta Spells:13% Bêta Arts & graphics:70%
Je ne comprends pas... Quand on fait quelque chose comme :
Gui:
Trigger:
Set Region_Point[1] = (Center of (Playable Map Area))
On leak aussi : on crée le point Center of playable Map Area, puis on lui assigne une variable. Certes, on ne l'aura créé qu'une fois, mais cela leak quand même nan ? _________________
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 31/05/08 16:16 Sujet du message:
The Shadow of Death a écrit:
Je ne comprends pas... Quand on fait quelque chose comme :
Gui:
Trigger:
Set Region_Point[1] = (Center of (Playable Map Area))
On leak aussi : on crée le point Center of playable Map Area, puis on lui assigne une variable. Certes, on ne l'aura créé qu'une fois, mais cela leak quand même nan ?
leak = fuite de mémoire, autrement dit quand quelque chose continue à prendre de la place en mémoire inutilement.
Si tu continues à utiliser la variable, alors tu ne leak pas car tu as toujours besoin du point référencé dans cette variable.
Par contre si tu n'en a plus besoin tu peux en effet détruire le point, mais si tu dois te soucier d'un seul point , achète de la mémoire vive koa _________________
Le "leak" est une perte de mémoire, c'est à dire un emplacement dans la mémoire qui ne peut plus être utilisé car non-référencé, à ne pas mélanger avec de la mémoire utilisée inutilement comme dans le cas d'un point que tu n'utilises plus et que tu gardes stocké dans une variable.
Mais si par exemple tu fais quelque chose du genre :
Gui:
Trigger:
Set Region_Point[1] = (Center of (Playable Map Area)) Set Region_Point[1] = (Center of (Playable Map Area))
Tu auras un leak sur le premier point, je m'explique :
La fonction (Center of (Playable Map Area)) créé un point, avec les coordonnées du centre de la région.
Lorsque tu l'utilises pour la première fois, tu enregistres "l'addresse" de cet "objet" point, dans la variable.
Lorsque tu l'utilises à nouveau, tu remplaces cette addresse par une nouvelle pointant sur un nouveau point créé lui aussi à partir de la zone en question.
On perd alors tout moyen d'acceder à la première addresse, donc on ne pourra alors ni utiliser le point, ni le supprimer.
De la mémoire est alors "perdue" jusqu'à la fermeture de la map. _________________
Bêta Systems:70% Bêta Spells:13% Bêta Arts & graphics:70%
Toutes les heures sont au format GMT + 1 Heure Aller à la page 1, 2, 3, 4Suivante
Page 1 sur 4
Vous ne pouvez pas poster de nouveaux sujets dans ce forum Vous ne pouvez pas répondre aux sujets dans ce forum Vous ne pouvez pas éditer vos messages dans ce forum Vous ne pouvez pas supprimer vos messages dans ce forum Vous ne pouvez pas voter dans les sondages de ce forum