Forums Développement Multimédia

Aller au contenu

Vider la mémoire des images chargées sur un serveur

PAO Flash

16 réponses à ce sujet

#1 FredericHunter

    Ceinture Jaune

  • Members
  • PipPip
  • 28 messages

Posté 31 March 2013 - 19:21 PM

bonjour, je suis très très novice, et m'excuse par avance si je n'emplois pas les bons termes. Je vais essayer d'expliquer mon soucis clairement. Je travaille sur un "livre dont vous êtes le héros" en amateur, avec un petit groupe de jeunes, pour tablette (AIR)... nous l'avons terminé (non sans difficultés !)... mais voilà, nous rencontrons un nouveau soucis (et j'avoue que ça commence à être difficile)...

Nous utilisons une "séquence" pour chaque chapitre. Sur chaque "image-clé", il y a un choix, du genre, "prendre à gauche" ou "prendre à droite", qui renvoie ensuite à une autre "image clé" (une position dans la séquence). Pour ne pas surcharger la mémoire, les images de fonds du livre sont chargées dans un clip dans un calque tout en bas de la séquence, en direct, avec le code suivant :




var conteneurImage11:Loader = new Loader();
var image11:URLRequest = new URLRequest("www.adresse.fr/image1.jpg");conteneurImage11.load(image11);
this.addChild(conteneurImage11);
 


... et comme ça pour toutes les images de fond, dans un clip différent.

... alors, comme ça, tout marche bien sur PC... mais sur tablette, au bout d'une quinzaine d'images chargées, le jeu ralentit énormément... j'ai pensé que ça pouvait venir de toutes les images chargées qui prenaient de la place. Je n'en suis même pas sûr... Et je me demandais comment je peux faire pour libérer de la mémoire, voire supprimer les images, quitte à les recharger en cas de besoin ? N'y aurait-il pas un code pour "purger" la mémoire des images chargées ?

[j'espère être clair, excusez mon inexpérience, ce n'est vraiment pas ma spécialité, et je fais de mon mieux]

merci beaucoup,
Frederic

#2 Goabonga

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2724 messages

Posté 31 March 2013 - 19:54 PM

Slt, y'a une methode unload sur l'objet Loader :)

#3 FredericHunter

    Ceinture Jaune

  • Members
  • PipPip
  • 28 messages

Posté 31 March 2013 - 20:08 PM

bonjour, merci...

est-ce que, dans cet exemple, je peux mettre dans l'image clé suivante >


conteneurImage11:unload();
 

... et ainsi de suite pour toutes les images clés ?

> EDIT : bon, j'ai essayé, et il m'indique

Séquence 1, Calque 'unload()', Image 2, ligne 1 1180: Appel à une méthode qui ne semble pas définie, unload.
 

ai-je mal écrit le code ? ou est-ce que ça vient que mon code initial (loader) se trouver dans un clip ?
merci :)

#4 FredericHunter

    Ceinture Jaune

  • Members
  • PipPip
  • 28 messages

Posté 31 March 2013 - 20:36 PM

petit complément (sans doute important)

en position 1

j'ai un clip appelé en occurence "paysage1" dans lequel il y a le code


var conteneurImage11:Loader = new Loader();
var image11:URLRequest = new URLRequest("www.adresse.fr/image1.jpg");conteneurImage11.load(image11);
this.addChild(conteneurImage11);
 

en position 2, je veux effacer cette image, j'ai essayé :

conteneurImage11.unloadAndStop();
 


_paysage1.conteneurImage11.unloadAndStop();
 

... mais j'ai des erreurs...


**-**

EDIT, j'ai copié un tel code (et l'ai adapté)


function unloadSWF(event:Event):void {
   paysage1.unloadAndStop();

removeChild(paysage1);
   paysage1 = null;
}
 

... comment savoir si ça marche, que la mémoire est libérée ? (je n'ai pas d'erreur)

#5 Goabonga

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2724 messages

Posté 31 March 2013 - 21:11 PM

pourquoi : ?
conteneurImage11:unload();

conteneurImage11.unload();

puis :


System.gc();
var mem:String = Number( System.totalMemory / 1024 / 1024 ).toFixed( 2 ) + ‘Mb’;
trace( mem );
 

System.gc() force le passage du GarbageCollecor en mode debug.
http://help.adobe.co...System.html#gc()

#6 Nataly

    Community Jane

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 5783 messages

Posté 01 April 2013 - 14:46 PM

salut :)

je n'ai pas forcément suivi : tu as une seule instance de Loader ou une par image ? c'est le conteneurImage11 qui me met la puce à l'oreille ;)

il me semble qu'il serait préférable d'avoir une seule instance de Loader que tu chargerais d'un nouveau fichier à chaque fois, ce qui simplifierait.

sans quoi,

Voir le messageFredericHunter, le 31 March 2013 - 20:08 PM, dit :

est-ce que, dans cet exemple, je peux mettre dans l'image clé suivante >
conteneurImage11:unload();


• non si conteneurImage11 n'est plus sur l'image courante (par exemple contenu ds un clip qui n'y serait plus),
• non si tu as vraiment utilisé "deux points" ;)
• oui ds le cas contraire, mais il faut, en plus, supprimer ce chargeur (removeChild) s'il est précisément destiné à une image et une seule et que tu en crées un autre pour l'image suivante.

Le mieux donc c'est un seul chargeur : à chaque load un unload est invoqué automatiquement, tu n e multiplieras donc pas les images.

Si tu charges des animations, décharge explicitement avant de charger en utilisant unloadAndStop


++ :)
Le savoir est le seul bien qui s'accroit quand on le partage
une tartine de tutos

#7 FredericHunter

    Ceinture Jaune

  • Members
  • PipPip
  • 28 messages

Posté 02 April 2013 - 07:47 AM

bonjour Goabonga, merci de ton retour...

pour le second script (dont je ne comprends pas à quoi il sert), il me note une erreur ?


System.gc();
var mem:String = Number( System.totalMemory / 1024 / 1024 ).toFixed( 2 ) + ‘Mb’;
trace( mem );
 

... comme je ne l'ai pas compris, je n'ai rien changé, devais-je personnaliser un paramètre ? (je l'ai mis à la suite, comme ça)

function unloadSWF(event:Event):void {
   paysage1:unloadAndStop();

removeChild(paysage1);
   paysage1 = null;
}

System.gc();
var mem:String = Number( System.totalMemory / 1024 / 1024 ).toFixed( 2 ) + ‘Mb’;
trace( mem );
 

merci

#8 FredericHunter

    Ceinture Jaune

  • Members
  • PipPip
  • 28 messages

Posté 02 April 2013 - 07:50 AM

bonjour Nataly,
je vais m'imprimer tes explications, car j'ai du mal à suivre... je vais lire tout ça à tête reposer. MERCI.... :) je reviens après, quoiqu'il en soit, réussi ou pas. A tout à l'heure.

nb : pour répondre à ta question, oui, j'ai plein de "Loader", un par chaque "image clé" (image de fonds)... je me doute que ce doit être du "bricolage", mais je ne suis vraiment pas un expert, je débute...

#9 Goabonga

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2724 messages

Posté 02 April 2013 - 08:35 AM

Salut
le bout de code répond à la question

Citation

... comment savoir si ça marche, que la mémoire est libérée ? (je n'ai pas d'erreur)

petit exemple :

package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.system.System;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;

public class App extends Sprite
{
  private var _info:TextField;

  public function App()
  {
   if(stage)init();
   else addEventListener(Event.ADDED_TO_STAGE,init);
  }
  protected function init(event:Event=null):void
  {
   if(event)removeEventListener(Event.ADDED_TO_STAGE,init);
   //
   stage.scaleMode = StageScaleMode.NO_SCALE;
   stage.align = StageAlign.TOP_LEFT;
   //
   _info = new TextField();
   _info.autoSize = TextFieldAutoSize.LEFT;
   _info.defaultTextFormat = new TextFormat('Verdana',9);
   _info.selectable = false;
   _info.text = 'init';
   addChild(_info);
   //
   addEventListener(Event.ENTER_FRAME,render);
   stage.addEventListener(Event.RESIZE,resize);
   //
   resize();

  }

  protected function resize(event:Event = null):void
  {
   _info.x = 5;
   _info.y = stage.stageHeight - _info.height -5;
  }

  protected function render(event:Event):void
  {
   System.gc();
   _info.text =  String(Number( System.totalMemory / 1024 / 1024 ).toFixed( 2 ) )+ 'Mb';
  }
}
}
 



- Afficher le SWF -
Fichier joint  App.swf   1.26 Ko   1 téléchargement(s)

#10 Goabonga

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2724 messages

Posté 02 April 2013 - 08:57 AM

Puis un exemple a décortiquer :


package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.net.URLRequest;
import flash.system.System;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.ui.Keyboard;

public class App extends Sprite
{
  private var _info:TextField;
  private var _lock:Boolean;
  private var _loader:Loader;
  private var _request:URLRequest;
 
  public function App()
  {
   trace(this);
   if(stage)init();
   else addEventListener(Event.ADDED_TO_STAGE,init);
  }
  protected function init(event:Event=null):void
  {
   trace(this,'init',event);
   if(event)removeEventListener(Event.ADDED_TO_STAGE,init);
   //
   stage.scaleMode = StageScaleMode.NO_SCALE;
   stage.align = StageAlign.TOP_LEFT;
   //
   _info = new TextField();
   _info.autoSize = TextFieldAutoSize.LEFT;
   _info.defaultTextFormat = new TextFormat('Verdana',9);
   _info.selectable = false;
   _info.text = 'init';
   addChild(_info);
   //
   addEventListener(Event.ENTER_FRAME,render);
   stage.addEventListener(Event.RESIZE,resize);
   //
   stage.addEventListener(KeyboardEvent.KEY_UP,keyboard);
   //
   resize();
 
  }
 
  protected function keyboard(event:KeyboardEvent):void
  {
   trace(this,'keyboard',event);
   if(_lock) return;
 
   switch(event.keyCode)
   {
    case Keyboard.NUMBER_1:
    {
         _request = new URLRequest('ico_32.png');
         load();
         break;
    }
    case Keyboard.NUMBER_2:
    {
         _request = new URLRequest('ico_36.png');
         load();
         break;
    }
    case Keyboard.NUMBER_3:
    {
         _request = new URLRequest('ico_48.png');
         load();
         break;
    }
    case Keyboard.NUMBER_4:
    {
         _request = new URLRequest('ico_58.png');
         load();
         break;
    }
    case Keyboard.NUMBER_5:
    {
         _request = new URLRequest('ico_72.png');
         load();
         break;
    }
    case Keyboard.NUMBER_6:
    {
         _request = new URLRequest('ico_100.png');
         load();
         break;
    }
       
    default:
    {
         break;
    }
   }
  }
 
  private function load():void
  {
   trace(this,'load');
   _lock = true;
   if(_loader){
    unload();
    return;
   }
 
   _loader = new Loader();
   _loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaded);
   _loader.load(_request);
  }
 
  private function unload():void
  {
   trace(this,'unload');
   removeChild(_loader);
   _loader.contentLoaderInfo.addEventListener(Event.UNLOAD,unloaded);
   _loader.unload();
  }
 
  protected function unloaded(event:Event):void
  {
   trace(this,'unloaded',event);
   _loader.contentLoaderInfo.removeEventListener(Event.UNLOAD,unloaded);
   _loader = null;
   _lock = false;
   load();
  }
 
  protected function loaded(event:Event):void
  {
   trace(this,'loaded',event);
   _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,loaded);
   addChild(_loader);
   resize();
   _lock = false;
  }
 
  protected function resize(event:Event = null):void
  {
   trace(this,'resize',event);
   _info.x = 5;
   _info.y = stage.stageHeight - _info.height -5;
   //
   if(!_loader) return;
   _loader.x = stage.stageWidth *.5- _loader.width*.5;
   _loader.y = stage.stageHeight *.5 - _loader.height *.5;
  }
 
  protected function render(event:Event):void
  {
   //trace(this,'render',event);
   System.gc();
   _info.text =  String(Number( System.totalMemory / 1024 / 1024 ).toFixed( 2 ) )+ 'Mb';
  }
}
}
 

;)

#11 Nelchaël

  • Members
  • PipPipPipPipPipPipPipPip
  • 1900 messages

Posté 02 April 2013 - 10:53 AM

Quelques compléments :

- Une alternative plus ou moins connue à system.gc :
try
        {
        new LocalConnection().connect("gc");
        new LocalConnection().connect("gc");
        }
catch(er_:Error)
        {
        }
Ce n'est pas une méthode officielle, mais, sur mon ancien pc, il n'y avait que ça qui marchait.

- Ce qui permet également de vérifier que le nettoyage forcé de la mémoire s'effectue : si tu supprimes un clip en lecture automatique avec du code sur une image comme un trace, le code ne s'exécutera plus. C'est une confirmation de plus si tu as un doute sur la quantité de mémoire affichée...

- En complément à unload, close peut s'avérer utile.
Exemple que je vois dans un de mes anciens codes :
try
        {
        lr_.close();
        this.initialiser();
        }
catch(er_:Error)
        {
        //si succès chargement
        if(this.bl_succChar===true)
                {
                lr_.contentLoaderInfo.addEventListener(Event.UNLOAD,this.quandFinDechargement);
                lr_.unloadAndStop();
                }
        else
                {
                this.initialiser();
                }
        }

nelchael.fr freelance flash CS6

#12 Nataly

    Community Jane

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 5783 messages

Posté 02 April 2013 - 11:01 AM

goa m'a fichu le doute

donc si tu veux être sûr (pour peu que ta construction s'y prête, les séquence c'est la galère) tu pourrais déclarer image 1 du scénario :
• une variable de type Loader, valorisé
• une fonction qui vire les écouteurs de l'instance courante (pour peu qu'elle existe) et l'écrase par une nouvelle avec ses nouveaux écouteurs

genre : (pas testé à l'arrache :oops: )

var _ldr_c:Loader;
var _ldrInfo:LoaderInfo;

function nouveau() {

        if (_ldr_c) {
                _ldrInfo.removeEventListener(Event.OPEN, ouvre);
                _ldrInfo.removeEventListener(Event.INIT,init);
                _ldrInfo.removeEventListener(Event.COMPLETE, finChargement);
                _ldrInfo.removeEventListener(Event.UNLOAD, décharge);
        }
        _ldr_c= new Loader();
    _ldrInfo= _ldr_c.contentLoaderInfo
        _ldrInfo.addEventListener(Event.OPEN, ouvre);
        _ldrInfo.addEventListener(Event.INIT,init);
        _ldrInfo.addEventListener(Event.COMPLETE, finChargement);
        _ldrInfo.addEventListener(Event.UNLOAD, décharge);

}

 

et à chaque image tu n'as plus qu'à écrire :


nouveau();
_ldr_c.load(new URLRequest(………)
 


:roll: SGDG

[Edit] heureux que je me sois relue après coup, c'était tout plein de coquilles/oublis

Modifié par Nataly, 02 April 2013 - 12:51 PM.
modif du code proposé

Le savoir est le seul bien qui s'accroit quand on le partage
une tartine de tutos

#13 Nataly

    Community Jane

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 5783 messages

Posté 02 April 2013 - 11:03 AM

Salut Nelchaël ! :)

dois-je comprendre que tu proposes un moyen pour forcer le passage du ramasse miette en dehors d'une cession de débug ?? Ô.Ô
Le savoir est le seul bien qui s'accroit quand on le partage
une tartine de tutos

#14 Goabonga

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2724 messages

Posté 02 April 2013 - 11:18 AM

L'astuce de générer une erreur en donnant le meme nom à deux local connection permet surtout au player avant le 9.4.*** de faire passer le GC (un bug de l'epoque).

Ne surtout pas utiliser en prod car, l'erreur génère une montée en charge sur le processeur !

Par contre, Nataly je ne remets pas ton expérience en question, mais je te fais juste part de la mienne :)

(bien vu pour la remarque du close, j'utilise une var _lock pour éviter de l'utiliser)

Autre remarque il faut favoriser l'utilisation du Profiler qui offre une vision plus clair et direct de l'utilisation des ressources ...

#15 Nelchaël

  • Members
  • PipPipPipPipPipPipPipPip
  • 1900 messages

Posté 02 April 2013 - 18:36 PM

Voir le messageGoabonga, le 02 April 2013 - 11:18 AM, dit :

L'astuce de générer une erreur en donnant le meme nom à deux local connection permet surtout au player avant le 9.4.*** de faire passer le GC (un bug de l'epoque).
C'est bien possible.
Apparemment, pour le cas particulier de mon ancien ordinateur, le system.gc ne marchait pas non plus sur la version 11 (version de débogage) alors que sur le nouveau, c'est bon.
J'avais lu également comme solution de doubler le system.gc mais rien à faire, c'est pourquoi j'avais cherché une autre piste.

Nataly, mon intention était plus de signaler une autre solution dans le cas où system.gc ne passait pas du tout, que de donner une méthode plus générale. ;)
nelchael.fr freelance flash CS6

#16 Goabonga

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 2724 messages

Posté 02 April 2013 - 18:49 PM

Re ;)

Tu peux me dire c'est quoi comme machine, l'os ...?



#17 Nelchaël

  • Members
  • PipPipPipPipPipPipPipPip
  • 1900 messages

Posté 02 April 2013 - 19:25 PM

Oui, c'était un XP familial, à priori à jour.
Je compilais sous Flash CS6.
Par contre, c'était un très vieux portable (2004) avec des problèmes étranges, une RAM très insuffisante etc.

(Autre souci au passage : l'export vers AIR était impossible (blocage immédiat avec un message d'erreur et fermeture forcée de Flash obligatoire).
Apparemment d'autres avaient eu ce souci, je crois me souvenir qu'Adobe avait indiqué une solution sur leurs forums (liée à Visual C++ mais je ne sais plus trop en fait), tout le monde n'arrivait pas à régler le problème malgré cela, et, de mon côté, je n'avais même pas essayé...)

Je l'ai toujours, mais bien rangé et avec Flash désactivé. ;)
nelchael.fr freelance flash CS6



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

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

authorised training centre

Centre de Formation Mediabox - Adobe et Apple Authorised Training Center.

Déclaré auprès de la Direction du Travail et de la Formation Professionnelle

Mediabox : SARL au capital de 62.000€ - Numéro d'activité : 11 75 44555 75 - SIRET : 49371646800035

MEDIABOX, 23, rue de Bruxelles, 75009 PARIS

FFP