11
votes

Vaut-il la peine d'atténuer contre les effets de la collecte des ordures?

J'ai une application où le profil de mémoire ressemble à quelque chose comme ceci:

 jaggy
(Source: Kupio.com )

La ralentissement de la mémoire de la mémoire est causée par l'allocation de lots et de nombreux objets simples, simples et transitoires. Dans des situations de mémoire basse mémoire (ceci est une application mobile), la surcharge GC est perceptible par rapport à des quantités de mémoire moins restrictives.

Depuis que nous savons, en raison de la nature de l'application, ces crèches continueront de rester à venir, je considérais une sorte de bassin d'objets transitoires multitudes (nom génial). Ces objets vivraient pour la durée de vie de l'application et être réutilisés dans la mesure du possible (où la durée de vie de l'objet est courte et hautement prévisible).

Espérons que cela atténuerait contre les effets de GC en réduisant le nombre d'objets collectés et améliorant les performances.

Évidemment, cela aurait également ses propres limites de performance depuis que "l'allocation" serait plus chère et il y aurait une surcharge dans le maintien du cache lui-même.

Étant donné que ce serait un changement assez important et intrusif en une grande quantité de code, je me demandais si quelqu'un avait essayé quelque chose de similaire et s'il s'agissait d'un avantage, ou s'il y avait d'autres moyens connus d'atténuer contre GC dans cette sorte de situation. Des idées pour des moyens efficaces de gérer un cache d'objets réutilisables sont également les bienvenus.


5 commentaires

"Grande cache d'objets latents multididineux" == piscine.


piscine == "Pas autant de plaisir à dire": p


Est-ce que vous savez vous obtenez des pauses?


piscine == "la terminologie standard".


Oui, il y a des pauses de GC. L'application est notablement plus lente la moins de mémoire est autorisée à l'application. Avec plus de mémoire, l'application se sent plus rapide mais tend à la GC quand elle importe moins pour l'utilisateur (essentiellement lorsqu'il y a un appel à système.gc () à des moments appropriés).


8 Réponses :


6
votes

Ceci est similaire au Flyweight motif détaillé Dans le livre des motifs GOF (voir Modifier ci-dessous). Pools d'objets sont sortis de faveur dans une machine virtuelle "normale" en raison des avancées effectuées dans la réduction de la création d'objets, de la synchronisation et des frais généraux de GC. Cependant, ceux-ci ont certainement été autour depuis longtemps et il convient certainement de les essayer de voir s'ils aident!

Certainement Les pools d'objets sont toujours utilisés pour des objets qui ont une génération de création très coûteuse par rapport aux frais généraux de mise en commun mentionnés ci-dessus ( Connexions de base de données Étant un exemple évident).

Seul un test vous indiquera si l'approche de la mise en commun vous convient sur vos plates-formes cible!

edit - J'ai pris l'op "réutilisé dans la mesure du possible" pour signifier que les objets étaient immuables. Bien sûr, cela pourrait ne pas être le cas et le modèle de poids fly est vraiment sur les objets immuables partagés ( Enum S étant un exemple de poids volé). Un objet mutable (lecture: inébranlable) n'est pas un candidat pour le modèle de vol de fly mais est (bien sûr) pour un pool d'objets.


2 commentaires

qui ne répond pas à la question suivante: si le pouvoir le faire


Je pensais que c'était un peu implicite dans la réponse. Si le GOF a écrit un livre qui comprenait cela comme un modèle commun, il s'ensuit qu'il s'agit d'une solution potentielle au problème



0
votes

Vous parlez d'un pool d'instances d'objet réutilisables.

class MyObjectPool { 
    List<MyObject> free= new LinkedList<MyObject>();
    List<MyObject> inuse= new LinkedList<MyObject>();
    public MyObjectPool(int poolsize) {
        for( int i= 0; i != poolsize; ++i ) {
           MyObject obj= new MyObject();
           free.add( obj );
        }
    }
    pubic makeNewObject( ) {
        if( free.size() == 0 ) {
            MyObject obj= new MyObject();
            free.add( obj );
        }
        MyObject next= free.remove(0);
        inuse.add( next );
        return next;
   }
   public freeObject( MyObject obj ) {
       inuse.remove( obj );
       free.add( obj );
   }
}
        return in


0 commentaires

2
votes

Normalement, je dirais que c'était un travail de réglage des paramètres GC de la machine virtuelle, de réduire les applications Spiky-Ness, mais pour les applications mobiles qui n'est pas vraiment une option. Donc, si les JVM que vous utilisez ne peuvent pas avoir leur comportement GC modifié, puis la mise en commun de l'objet à l'ancienne peut être la meilleure solution.

La bibliothèque de piscine Apache Commons est bonne pour cela, bien que s'il s'agisse d'une application mobile, vous ne voulez peut-être pas que la dépendance de la bibliothèque dépend de la dépendance.


0 commentaires

0
votes

étant donné que Ce Réponse suggère qu'il n'y a pas beaucoup de possibilités pour modifier la collection de déchets elle-même dans J2ME, alors si GC est un problème que la seule autre option consiste à examiner la manière dont vous pouvez modifier votre application pour améliorer l'utilisation des performances / de la mémoire. Peut-être que certaines des suggestions de la réponse référencées s'appliqueraient à votre application.

Comme Oxbow_Lakes dit, ce que vous suggérez est un modèle de conception standard. Cependant, comme pour toute optimisation, le seul moyen de savoir vraiment combien il améliorera votre application particulière consiste à mettre en œuvre et en profilant.


0 commentaires


2
votes

En fait, ce graphique me semble assez en bonne santé. Le GC recueille beaucoup d'objets et la mémoire revient ensuite au même niveau de base. Empiriquement, cela signifie que le GC fonctionne efficacement.

Le problème avec la mise en commun de l'objet est qu'il rend votre application plus lente, plus compliquée et potentiellement plus buggy. Quoi de plus, cela peut réellement rendre chaque gui gc prendre plus de temps. (Tous les objets "inactifs" dans la piscine sont des non-ordures et doivent être marqués, etc. par le GC.)


0 commentaires

2
votes

J2ME a-t-il un collecteur de déchets générationnels? Si c'est le cas, il fait de nombreux petits, rapides, collections et donc les pauses sont réduites. Vous pouvez essayer de réduire l'espace mémoire Eden (le petit espace mémoire) pour augmenter la fréquence et réduire la latence des collections et réduire ainsi les pauses.

Bien que, viennent y penser, je suppose que vous ne pouvez pas ajuster le comportement GC car tout fonctionne probablement dans le même VM (juste une devinière ici).


0 commentaires

1
votes

Vérifiez Ce lien . En particulier:

juste pour énumérer quelques problèmes Piscines d'objets Créez: d'abord un inutilisé objet prend un espace mémoire pour non raison; Le GC doit traiter l'inutilisé objets aussi bien, le détenir sur objets inutiles sans raison; et en afin de chercher un objet de la objet piscine une synchronisation est généralement requis qui est beaucoup plus lent que l'allocation asynchrone Disponible de manière nativement.


0 commentaires