IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Mono .NET Discussion :

Mono embed: Objet punaisé et problème de GC (Garbage)


Sujet :

Mono .NET

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Avril 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Avril 2015
    Messages : 10
    Points : 7
    Points
    7
    Par défaut Mono embed: Objet punaisé et problème de GC (Garbage)
    Bonjour,

    Dans le cadre d'un projet personnel, une "AI" pour un jeu, j'avais besoin d'embarquer Mono dans une librairie dynamique C++, sous Linux (Ubuntu 14.04).
    J'ai utilisé SWIG pour avoir un wrapper C++/C#. Le projet fonctionne très bien mais l'occupation mémoire devient trop importante au bout d'un moment car le ramasse-miette ne semble pas faire son travail.
    J'ai testé avec le simple remplissage d'une liste, et effectivement, la mémoire n'est pas libérée au fil des appels.
    J'ai cru comprendre que Mono-Embed avait un problème récurrent du côté du ramasse-miette?

    Pour le process:
    Le jeu démarre et ensuite charge pour chaque AI, la librairie C++

    Comme il peut y avoir plusieurs instances de mon AI, j'ai créé un gestionnaire (une classe):
    La première instance d'AI initialise créé ce gestionnaire et l'initialise:
    - mono_jit_init()
    - création d'un object et init (callback,etc). pour l'AI avec mono_gchandle_new() (sinon l'objet est détruit entre les appels)

    Puis les autres AI (s'il y en a):
    - création d'un object et init (callback,etc). pour l'AI avec mono_gchandle_new()

    Durant le jeu:
    Chaque AI est appelé au fil des événements:
    Appels avec mono_runtime_invoke() pour l'object mono concerné.
    La librairie Mono peut communiquer au jeu également via le callback.

    A la fermeture du jeu, la dernière AI ferme le gestionnaire:
    mono_jit_cleanup() etc



    Si je n'utilise pas mono_gchandle_new() pour punaiser ("pinned") mes objets, ils sont rapidement détruits par Mono.
    J'ai essayé avec mono_gchandle_new_weakref() mais même problème.

    J'ai essayé également en appelant directement et régulièrement le GC depuis le C++ avec mono_gc_collect (mono_gc_max_generation ()) mais rien y fait.

    Du coup, est ce que le ramasse miette fonctionne sur les objets punaisés?

  2. #2
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Essaie de remplacer l'appel au garbage collector par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    GC.Collect() ; GC.WaitForPendingFinalizers() ; GC.Collect()
    en sachant qu'il y a/avait une bug dans la version 3.4.0/3.8.0 de Mono : https://bugzilla.xamarin.com/show_bug.cgi?id=20503
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Avril 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Avril 2015
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    J'avais déjà essayé de forcer la collecte côté C# également (celle côté C++ est limitée à une fonction)

    J'ai retesté avec:

    GC.Collect() ; GC.WaitForPendingFinalizers() ; GC.Collect()

    au lieu de:

    GC.Collect() ; GC.WaitForPendingFinalizers() ;

    La collecte ne se fait toujours pas pour autant. A croire que les objets créés par un objet punaisé sont également punaisés et donc non-collectables?

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Avril 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Avril 2015
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Finalement, j'utilise le handle d'un objet pour rappeler un objet par la suite et appeler ses méthodes. J'ai remarqué qu'il n'était pas nécessaire de les punaiser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Objects[team].Instance  = mono_object_new (Domain, Class); // Create instance (memory)
    mono_runtime_object_init (Objects[team].Instance); //Call constructor
    Je garde la mains sur mes objets (mais toujours le problème du GC) si je récupère le handle ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Objects[team].handle = mono_gchandle_new (Objects[team].Instance, false);  // (true ou false ne change rien)
    Par contre si je récupère le handle de cette manière:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Objects[team].handle = mono_gchandle_new_weakref (Objects[team].Instance, false);  //(true ou false ne change rien)
    je garde la main sur un seul objet et les autres sont nettoyés entre les appels.

  5. #5
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Bravo pour ta résolution du problème .

    Comme le garbage collector est gourmand en CPU, on peut éviter de l'appeler si il y a suffisament de mémoire libre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     long [,] TheArray ;
     try   { TheArray = new long[SizeToAllocateInMo,125000] ; } 
     catch { TheArray = null ; /* ... appel au garbage collector */ ; }
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Avril 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Avril 2015
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Hélas, non, le problème n'est pas résolu. C'est juste que les objets ne sont plus punaisés maintenant ("pinned"). Le GC continue à bouder la partie C#.

  7. #7
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    As-tu bien vérifié les problèmes potentiels liés à des liens Parent ou Child impliquant les objets à libérer, ainsi que les éventuelles inscriptions sur des events ?
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Avril 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Avril 2015
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    Merci pour tes réponses.

    Oui, il y a sûrement des fuites dues à une mauvaise gestion de mes objets (dés-allocations) dans mon code, mais le GC n'est vraisemblablement pas actif sur mes objets puisque le fait de remplir uniquement un tableau comme dans ton exemple, fait que la mémoire ne jamais désemplie. Donc il apparaît qu'utiliser mono_gchandle_new() fait que l'objet n'est pas ramassé côté C++ mais qu'il n'en occupe pas du tout. (côté C# aussi du coup). C'est assez logique finalement avec le recul.

    Du coup, pour contourner mon problème, au lieu de créer un objet par AI, je vais créer un seul objet qui va gérer (créer et aiguiller les appels vers les AI). Avec un seul objet je peux utiliser mono_gchandle_new_weakref()


    Mes premiers tests rapides avec 3 AI semblent prometteurs car la mémoire plafonne rapidement et oscille entre 500 et 600Mo ce qui indique bien qu'il y a ramassage en cours de route.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    namespace Embed 
    {
    	static public class Loader
    	{
    		static Dictionary<int,IA> test=new Dictionary<int, IA>();
     
    		public static void AddIA(ref int teamid)
    		{
    			test.Add(teamid,new IA());
    		}
     
    		public static void Update(ref int teamid,ref int frame)
    		{
    			test[teamid].Update(frame);
    		}
    	}
     
     
    	public class IA
    	{
    		public void Update(int frame)
    		{
    			long [,] TheArray ;
    			try   { TheArray = new long[40,125000] ; } 
    			catch { TheArray = null ;  ; }
    		}
    	}
    }
    Je vais continuer à modifier mon code avec cette nouvelle approche et voir qu'il n'y a pas de mauvaises surprises plus loin.

    Edit:

    Au bout d'un moment, l'objet est ramassé sans aucune raison vu que je fais des appels (en utilisant son handle);

    Si je n'utilise pas de handle mais directement son pointeur, l'objet n'est pas ramassé. (a priori)
    Le ramassage est plus tardif mais a lieu.

    Edit:
    Le moindre appel à la librairie C++ nécessite de devoir disposer les ressources ensuite. Je pensais que le ramasse miette le ferait, mais que nenni.

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Avril 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Avril 2015
    Messages : 10
    Points : 7
    Points
    7
    Par défaut
    En se limitant à un seul objet, le punaisage et la gestion par handle ne sont plus nécessaires (le pointeur sur l'objet suffit). Le GC semble fonctionner correctement maintenant que les ressources sont libérées après leur utilisation. Je considère comme résolu le sujet.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2007] Objets conteneurs et problème de raffraichissement?
    Par Vhalar dans le forum IHM
    Réponses: 8
    Dernier message: 05/09/2011, 11h21
  2. Problème lié au Garbage collector
    Par yohannc dans le forum Général Java
    Réponses: 2
    Dernier message: 28/12/2010, 12h16
  3. [SL3] Problème avec le garbage collector
    Par DarkLeon dans le forum Silverlight
    Réponses: 3
    Dernier message: 24/06/2010, 12h14
  4. [FLASH MX] Problème avec l'objet Date
    Par n_tony dans le forum Flash
    Réponses: 13
    Dernier message: 22/03/2005, 13h44
  5. [C#] Problème pour l'appel d'objet...
    Par AntiSAL dans le forum Windows Forms
    Réponses: 2
    Dernier message: 14/06/2004, 09h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo