Forums Développement Multimédia

Aller au contenu

Mon application rame ...

CODE Actionscript

14 réponses à ce sujet

#1 causta

    Ceinture Jaune

  • Members
  • PipPip
  • 21 messages

Posté 12 June 2013 - 12:55 PM

Bonjour à tous,

j'ai un gros problème et là je ne comprend plus ...

Voici ma problématique :
- Je charge en mémoire une carte (jusque là pas de problème), quand je clic sur une partie de la carte, le reste disparait et cette partie s’agrandit au centre
- A chaque fois que j'affiche un clip et que je le supprime, je m'assure de le rendre éligible au ramasse miette, jusque là pas de problème, la mémoire ne bronche pas.
- là ça se complique, je charge un contenu dynamique en me basant sur un fichier XML.
- Ce fichier XML me permet de récupérer un certain nombre de photos d'un dossier externe.
- Quand je ferme le clip contenant tout ça, je m'assure de supprimer l'ensemble des clips enfants
- La mémoire augmente moins qu'avant que je ne supprime réellement l’ensemble de ces éléments, mais elle augmente quand même encore et au bout d'un moment ça rame ...
- Au lancement de l'application je suis dans les environs de 95Mo de mémoire, et au moment où ça commence à vraiment ramer je ne suis pourtant que entre 130 et 150 Mo d'utilisation de la mémoire.
- La 1ère version de mon programme, où je ne faisais que des removeChild sans mettre à null mes clips, pouvait atteindre facilement plus de 900Mo de mémoire mais ne ramait qu'à partir de 400 Mo ...
- je remarque que ça rame car quand je lis une vidéo, au 1er lancement c'est super fluide, et plus j'utilise mon application, plus la mémoire gonfle, et plus la vidéo saccade ...

- Je ne pense pas que ce soit lié à la mémoire mais peut être à une surcharge d’événement ?

Je suis encore assez débutant en Action Script, et il doit me manquer quelque chose d'essentiel ...

Ci joint mon code source, un peu codé avec les pieds ... j'espère que l'un d'entre vous pourra me donner des pistes ... car je désespère ...


Merci d'avance !
Très bonne journée à vous :)

Fichier(s) joint(s)

  • Fichier joint  src.zip   17.13 Ko   17 téléchargement(s)

Léandre

#2 Benzouye

  • Members
  • PipPipPipPipPipPipPipPip
  • 583 messages

Posté 12 June 2013 - 13:27 PM

Salut Causta,

Ton problème ne pourra pas être résolu avec le ramasse-miettes, il est d'ailleurs complètement inutile de le lancer manuellement comme tu le fais, car le player gère cela relativement bien et ne lance le gc que lorsque nécessaire. Dans ton cas, le gc ne trouve rien d'éligible à la suppression. Cela signifie que les objets que tu penses être éligibles ne le sont pas.
Pour être éligible un objet doit être null et ne plus avoir de références externes (écouteurs et pointeurs).
Lorsqu'un objet est éligible ses enfants le seront également, comme Didier et Galacta le rappellent pertinemment ici ... c'est l'effondrement pyramidal.

Dans ton cas, que je viens de parcourir très rapidement, je ne vois pas où et comment tu désactiverais tes clips et leurs références ?

Autre remarque hors sujet mais importante, tu devrais rapidement te mettre aux tableaux pour stocker tes objets et constantes !
Quelle perte d'énergie pour répéter x fois les mêmes lignes de code alors qu'une boucle for sur un tableau serait tellement plus efficace et lisible ...

J'essayes de regarder plus profondément ton code pour te faire un retour ... sans garantie ...

Modifié par Benzouye, 12 June 2013 - 13:29 PM.

Benzouye
Travaille avec FlashDevelop 4 + Flex SDK 4.6 open source

#3 causta

    Ceinture Jaune

  • Members
  • PipPip
  • 21 messages

Posté 12 June 2013 - 13:40 PM

Merci beaucoup pour ton retour !
comme dit, je suis un peu novice ...j'ai pas fais de flash depuis 6ans et la reprise, en AS3, a fait mal ...
J'ai tenté, tant bien que mal, de me mettre à niveau grâce au super cours de "Thibault IMBERT".

Les clips se désactivent dans ma classe nommée "Ile", tout à la fin j'ai des fonctions pour les supprimer.
Ces fonctions sont appelées dans un fichier que j'ai mis en "include" (pour faciliter la lecture ...) à travers des évènements.

J'avais en effet déjà lu tout ce topic concernant effondrement pyramidal, concept que je comprend parfaitement, mais j'ai remarqué que si je ne désactivais pas certaines images enfants, j'avais l'impression qu'elles restaient en mémoire.

Pour le coup du tableau, j'en ai déjà de créé, mais plus je débug mon programme, plus mes variables partent dans tous les sens ...

Si tu arrives à me trouver une piste, ça serait génial !!

Merci encore :)
Bonne après midi
Léandre

#4 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 12 June 2013 - 13:42 PM

Est-ce possible de voir un swf de la chose ou au moins de son principe ?

#5 Goabonga

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2724 messages

Posté 12 June 2013 - 13:45 PM

Tu dis que tu charges des images, est ce que tu les décharges ?

#6 causta

    Ceinture Jaune

  • Members
  • PipPip
  • 21 messages

Posté 12 June 2013 - 13:59 PM

Avant de supprimer les clip parent qui sert de conteneur, je ferme les images normalement.

Voici un lient pour récupérer le final : https://dl.dropboxus...85/Memorial.zip

Attention, il faut un écran tactile pour que ça fonctionne ... l'application n'a pas été prévu pour répondre à la souris ... (même avec la fonction simulator d'activé)
Léandre

#7 Benzouye

  • Members
  • PipPipPipPipPipPipPipPip
  • 583 messages

Posté 12 June 2013 - 16:03 PM

Dans ta classe Ile tu utilises la classe Image, avec une fonction getImage. Quelle est cette classe ? GestureWorks ?
En tout cas, je ne vois pas où tu les "décharges" ?

Sinon concernant le fonctionnement avec tableaux, ci-dessous un exemple de boucle pour alléger ta fonction gestureworksInit :
for ( var i:int = 0 ; i < nbIles ; i++ )
{
    var ile:Ile = new Ile( i , positionIle[i] , parametresIle[i] );
    ile.x = ile.posX;
    ile.y = ile.posY;
    ile.name = "Ile" + i;
   
    Iles.addChild( ile );
   
    ile.addChild ( ile.getNiveau1Ile() );
    addChild ( ile.getBoutonNiveau1() );
}

Du coup quelques changements dans ton constantes.as pour utiliser un tableau unique pour toutes les îles :
public static var positionIle:Array = new Array();
public static var parametresIle:Array = new Array();
positionIle.push = [CARTE_ILE1_X,...];
parametresIle.push = [[ZONE_TACTILE1_NIVEAU1_ILE1_X,...]];
// etc. pour chaque Ile

Benzouye
Travaille avec FlashDevelop 4 + Flex SDK 4.6 open source

#8 Goabonga

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2724 messages

Posté 12 June 2013 - 16:09 PM

le projet est la ;)

http://gestureworks.com/

#9 causta

    Ceinture Jaune

  • Members
  • PipPip
  • 21 messages

Posté 12 June 2013 - 16:26 PM

Merci beaucoup Benzouye !
Je vais tester ça dès ce soir !

Oui j'utilise la classe image inclus dans l'API Gestureworks.
voici l'adresse de l'API : http://files.gesture....com/flash-api/

Si jamais, je peux toujours vous envoyer intégralité de mon projet, on peut récupérer une version de 30jours de l'API gestureworks sur leur site.

Je test tout ça et je vous tiens au courant.
C'est vraiment sympa de m'aider ainsi !

Bonne fin de journée,
Léandre

#10 Goabonga

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2724 messages

Posté 12 June 2013 - 16:53 PM

Fais tu un dispose après le remove de tes objets Image ?

(fais un test avec une seul image pour voir s'il vide le loader .... quand on appelle la méthode dipsose )

#11 Benzouye

  • Members
  • PipPipPipPipPipPipPipPip
  • 583 messages

Posté 12 June 2013 - 16:53 PM

Bon je vais pollué le sujet avec du code, mais je n'arrive pas à uploader mon fichier .as :roll:
Ci-dessous ton projet réécris (sûrement très vite et avec plein de fautes) pour te donner une idée de la structure "normale" avec les tableaux.
Cela te permet d'y voir plus clair dans le code, et de ne pas avoir à te retaper 8 fonctions chaque fois que tu veux changer un truc ;) et ça évite les includes perturbateurs ...

Par contre je ne vois toujours pas où la surcharge se passe niveau performance ... :?

package
{
   import com.gestureworks.cml.core.*;
   import com.gestureworks.cml.element.*;
   import com.gestureworks.cml.events.*;
   import com.gestureworks.cml.managers.*;
   import com.gestureworks.cml.utils.*;
   import com.gestureworks.cml.components.*;
   import com.gestureworks.core.*;
   import com.gestureworks.events.*;
   import com.gestureworks.utils.*;
   
   import com.greensock.*;
   import com.greensock.easing.*;
   import com.greensock.plugins.*;
   
   import flash.system.*;
   import flash.events.*;
   import flash.display.*;
   import flash.net.*;
   import flash.ui.*;
   import flash.utils.*;
   import flash.geom.*;
   import flash.text.*;
   import flash.filters.*;
   import flash.filesystem.File;
   import flash.desktop.NativeApplication;
   import adobe.utils.ProductManager;
   
   public class Main extends GestureWorks
   {
          const DELAI_INACTIV:int = 300;//délai en secondes
          var _tempoInactiv:uint;//setInterval
          private var nbIles:int = 8;
          private var ileCible:Ile;
          private var tabIles:Array = new Array();

          include "inc/constantes.as"
         
          public function Main():void
          {
                 super();
                 Mouse.hide();
                 gml = "./assets/gestures.gml";
          }
         
          override protected function gestureworksInit():void
          {
                 // constructor code;
                 stage.addEventListener (MouseEvent.MOUSE_MOVE, moveActiv);
             
                 trace( "Init" , System.totalMemory );
             
                 fullscreen = true;
             
                 trace( "FullScreen" , System.totalMemory );
             
                 var Fond:Image = new Image  ;
                 Fond.open( "./assets/images/mer.jpg");
                 addChild(Fond);
             
                 var Iles:Container = new Container();
                 addChild(Iles);
                 Iles.name = "Conteneur Iles";
             
                 var Video1:MaVideo = new MaVideo("212",605,1000,100,90);
                 var Video2:MaVideo = new MaVideo("1",1105,0,100,80);
             
                 addChild(Video1);
                 addChild(Video2);
             
                 Video1.addChild(Video1.AfficherBoutonVideo());
                 Video2.addChild(Video2.AfficherBoutonVideo());
             
                 for ( var i:int = 0 ; i < nbIles ; i++ )
                 {
                    var ile:Ile = new Ile( i , positionIle[i] , parametresIle[i] );
                   
                    tabIles.push ( ile );
                   
                    ile.x = ile.posX;
                    ile.y = ile.posY;
                    ile.name = "Ile" + i;
                   
                    ile.addChild( ile.getNiveau1Ile() );
                    addChild ( ile.getBoutonNiveau1() );
                   
                    ile.addEventListener( Ile.TAP_ILE_NIVEAU1, Niveau1IleTouchee );
                    ile.addEventListener( Ile.AFFICHER_ILE_NIVEAU2, Niveau2IleAffichee );
                    ile.addEventListener( Ile.TAP_ILE_NIVEAU2_DANS_EAU, Niveau2IleDansEauTouchee );
                    ile.addEventListener( Ile.CACHER_ILE_NIVEAU2, Niveau2IleCachee );
                    ile.addEventListener( Ile.RESET_ILE_NIVEAU2, Niveau2IleSupprimee );
                    ile.addEventListener( Ile.TAP_ILE_NIVEAU2, Niveau2IleTouchee );
                    ile.addEventListener( 'mouseMove' , Niveau2IleTouchee );
                   
                    Iles.addChild( ile );
                 }
             
                 trace( "Fin add Iles" , System.totalMemory );
          }

          public function Niveau1IleTouchee( pEvt:Event ):void
          {
                 ileCible = pEvt.target;
             
                 for ( var i:int ; i < nbIles ; i++ )
                 {
                    if ( tabIles[i] !== ileCible )
                    {
                           tabIles[i].resetbtsNiveau1Ile();
                           TweenMax.To( tabIles[i] , 1, {autoAlpha:0, scaleX:0.9, scaleY:0.9, ease:Cubic.easeInOut, blurFilter:{blurX:100, blurY:100}}, 0.1, resetNiveau1AutresIles);
                    }
                    tabIles[i].removeEventListener( Ile.TAP_ILE_NIVEAU1, Niveau1IleTouchee );
                 }
             
                 ileCible.addChild( ileCible.getNiveau2Ile(true) );
                 Iles.setChildIndex( ileCible, ( Iles.numChildren - 1 ));
                 TweenMax.to(ileCible, 3, {x:((stageWidth / 2) - (CARTE_ILE1_WIDTH / 2)), y:((stageHeight / 2) - (CARTE_ILE1_HEIGHT / 2)), scaleX:1, scaleY:1, rotation:0, ease:Cubic.easeOut,onComplete:resetNiveau1Ile1});
             
                 ileCible.resetimgNiveau1Ile();
          }
             
          public function resetNiveau1Ile()
          {
                 //Ile1.resetimgNiveau1Ile();
                 TweenMax.killTweensOf(ileCible);
          }

          public function resetNiveau1AutresIles()
          {
                 for ( var i:int ; i < nbIles ; i++ )
                 {
                    if ( tabIles[i] !== ileCible )
                    {
                           tabIles[i].resetimgNiveau1Ile();
                           tabIles[i].addChild( Ile2.getNiveau2IleInactive() );
                           TweenMax.to ( tabIles[i], 1, {y:randomNumber(0,800) ,x:randomNumber(0,1700), autoAlpha:1, scaleX:0.6, scaleY:0.6, ease:Cubic.easeInOut, blurFilter:{blurX:0, blurY:0}});
                    }
                   
                    TweenMax.to( tabIles[i], 5, {autoAlpha:.9, repeat:-1, yoyo:true});
                 }
          }
         
          function Niveau2IleAffichee( pEvt:Event ):void
          {
                 ileCible = pEvt.target;
                 ileCible.addChild( pEvt.target.getNiveau2Ile(false) );
          }
         
          public function Niveau2IleDansEauTouchee( pEvt:Event ):void
          {
                 ileCible = pEvt.target;
                 if (Ile.getOuvertureIleAutorisee())
                 {
                    trace(ileCible.name);
                    ileCible.addChild( ileCible.getNiveau2Ile(true) );
                    ileCible.resetNiveau2IleInactive();
                    Iles.setChildIndex( ileCible, ( Iles.numChildren - 1 ));
                    var posXIle = ileCible.x-(ileCible.x/2);
                    if (posXIle < 0 )
                    {
                           posXIle = 50;
                    }
                    var posYIle = ileCible.y-(ileCible.y/2);
                    if (posYIle < 0)
                    {
                           posYIle = 50;
                    }
                    TweenMax.to(ileCible, 1, {x:posXIle, y:posYIle, autoAlpha:1, scaleX:1, scaleY:1, rotation:0,onComplete:resetNiveau2IleInactive});
                 }
          }
         
          public function resetNiveau2IleInactive()
          {
                 TweenMax.killTweensOf(ileCible);
                 //ileCible.removeEventListener( Ile.TAP_ILE_NIVEAU2_DANS_EAU, Niveau2IleDansEauTouchee );
          }
         
          public function Niveau2IleSupprimee( pEvt:Event ):void
          {
                 ileCible = pEvt.target;
                 Iles.setChildIndex( ileCible, ( Iles.numChildren - 1 ));
                 TweenMax.to ( ileCible, 1, { autoAlpha:0, scaleX:0.9, scaleY:0.9, ease:Cubic.easeInOut, blurFilter:{blurX:100, blurY:100},onComplete:resetNiveau2Ile});
          }
         
          public function Niveau2IleCachee( pEvt:Event ):void
          {
                 ileCible = pEvt.target;
                 ileCible.resetNiveau2Ile();
          }
         
          public function Niveau2IleTouchee( pEvt:Event ):void
          {
                 ileCible = pEvt.target;
                 ileCible.setChildIndex( pEvt.target , ( Iles.numChildren - 1 ) );
          }
         
          public function resetNiveau2Ile()
          {
                 ileCible.resetNiveau2Ile();
                 ileCible.addChild( ileCible.getNiveau2IleInactive() );
                 var posXIle = ileCible.x+(ileCible.x/2);
                 if (posXIle > 1800)
                 {
                    posXIle = ileCible.x-(ileCible.x/2);
                 }
                 var posYIle = ileCible.y+(ileCible.y/2);
                 if (posYIle > 900)
                 {
                    posYIle = ileCible.y-(ileCible.y/2);
                 }
                 TweenMax.to(ileCible, 1, {y:posYIle, x:posXIle, autoAlpha:1, scaleX:0.6, scaleY:0.6, ease:Cubic.easeInOut, blurFilter:{blurX:0, blurY:0}});
                 TweenMax.to(ileCible, 5, {autoAlpha:.9, repeat:-1, yoyo:true});
          }
         
          public function moveActiv(e:MouseEvent):void
          {
                 clearInterval(_tempoInactiv);
                 _tempoInactiv = setInterval(inactiv,DELAI_INACTIV * 1000);
          }
         
          public function inactiv():void
          {
                 clearInterval(_tempoInactiv);
                 restart();
          }
         
          public function restart():void
          {
                 var mgr:ProductManager = new ProductManager("airappinstaller");
                 mgr.launch("-launch " + NativeApplication.nativeApplication.applicationID + " " + NativeApplication.nativeApplication.publisherID);
                 NativeApplication.nativeApplication.exit();
          }
         
          public function randomNumber(min:Number, max:Number):Number
          {
                 return Math.floor(Math.random() * (1 + max - min) + min);
          }
   }
}

Benzouye
Travaille avec FlashDevelop 4 + Flex SDK 4.6 open source

#12 Galacta

    Etudiant Ingénieur

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 689 messages

Posté 12 June 2013 - 17:32 PM

Sinon y a le profileur d'Adobe pour ce genre de problème : Adobe Scout.

Si tu ne compiles pas avec ASC2, tu peux utiliser ScoutEnabler
Word hard, play hard.

#13 causta

    Ceinture Jaune

  • Members
  • PipPip
  • 21 messages

Posté 13 June 2013 - 10:25 AM

Wouaou, merci à vous, c'est cool de m'aider ainsi ! Si j'avais su, je serais venu un mois plus tôt ^^

@Goabonga : Oui je fais un dispose() quand je supprime mon clip avec une image
Par contre, une question dans ce sens là, est-ce que, si je ne fait pas de dispose(); ou ne supprimer pas mes clips enfants comportant des images, mais que je supprime uniquement mon clip parent, les images présentes dans les clips enfants seront-ils supprimées avec l'effondrement pyramidal ?

@Benzouye : trop sympa à toi, je vais tenter d'intégrer ça dans mon code, je pense avoir pigé le truc :)

@Galacta : je connaissais pas spécialement Adobe Scout, c'est super pratique :o. Je peux voir ainsi l'évolution et l'impacte de l'application.

Voici un lien pour récupérer mon log Adobe Scout :
- https://dl.dropboxus...ut-Memorial.zip
- est-ce que ce log permettrait de déterminer la raison de mes ralentissements ?


Je vais tester mon programme avec l'optimisation proposée par Benzouye et je vais déjà voir l'impacte que ça aura sur son utilisation.

Merci encore à tous :)
Léandre

#14 tlecoz

  • Honoris
  • PipPipPipPipPipPipPipPip
  • 3486 messages

Posté 13 June 2013 - 12:11 PM

Hello !

Citation

les images présentes dans les clips enfants seront-ils supprimées avec l'effondrement pyramidal ?
Non car ce n'est pas parce qu'un objet n'est pas ajouté à la displayList que cet objet n'existe pas

#15 Galacta

    Etudiant Ingénieur

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 689 messages

Posté 13 June 2013 - 14:24 PM

Il faut que tu active le tag advanced-telemetry si tu veux savoir d'où vient le problème. Ce tag te permet de suivre l'allocation / Desallocation des objets en mémoire. Ce sera plus clair, si tu peux le faire.

La sans ces infos, j'dirais que tes images ne sont jamais virées de la mémoire, tu n'aurais pas un écouteur encore dessus par hasard ? Ou une référence quelconque ?
Word hard, play hard.



1 utilisateur(s) li(sen)t ce sujet

0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)