Coût d’utilisation des références faibles en Java

Quelqu’un a-t-il étudié les coûts d’exécution liés à la création et à la collecte des objects Java WeakReference ? Existe-t-il des problèmes de performances (par exemple, des conflits) pour les applications multithread?

EDIT: Évidemment, la ou les réponses seront dépendantes de la JVM, mais les observations générales sont également les bienvenues.

EDIT 2: Si quelqu’un a effectué une parsing comparative de la performance, ou peut indiquer des résultats d’parsing comparative, ce serait idéal. (Désolé, mais la prime a expiré …)

WeakReferences ont un impact négatif sur le garbage collector du CMS. Pour autant que je puisse voir avec le comportement de notre serveur, il influence le temps de phase des remarques parallèles. Au cours de cette phase, tous les threads d’application sont arrêtés, ce qui est extrêmement indésirable. Donc, vous devez être prudent avec WeakReferences.

J’ai implémenté un garbage collector Java une fois, donc tout ce que j’ai pu accomplir est une limite inférieure (faible) sur ce qui est possible.

Dans mon implémentation, il y a une petite quantité constante de surcharge supplémentaire pour chaque référence faible lorsqu’elle est visitée lors du nettoyage de la mémoire.

Donc, le résultat est le suivant: je ne m’inquiéterais pas à ce sujet, ce n’est pas un gros problème à moins que vous n’utilisiez des milliers de références faibles.

Plus important encore, le coût est proportionnel au nombre de références faibles existantes, et non à la taille du tas global.

Cependant, cela ne veut pas dire qu’un ramasse-miettes prenant en charge les références faibles sera aussi rapide que celui qui ne le fait pas. La question présumée ici est que, étant donné que Java prend en charge les références faibles, quel est le coût supplémentaire de leur utilisation?

Le mien était un simple “arrêter le monde” marquer / ramasser le ramasse-miettes. Lors de la récupération de place, il détermine pour chaque object si cet object est actif ou non et définit un bit LIVE dans l’en-tête de l’object. Ensuite, il traverse et libère tous les objects non-vivants.

Pour gérer les références faibles, il vous suffit d’append ce qui suit:

  • Ignorez les références faibles lors de la définition des bits LIVE (c’est-à-dire qu’ils ne provoquent pas le réglage du bit LIVE sur l’object référencé).
  • Pendant l’étape de balayage, ajoutez une vérification spéciale comme suit: si l’object que vous visitez est LIVE et qu’il s’agit d’une WeakReference , vérifiez l’object référencé faiblement, et si cet object n’est pas LIVE , effacez la référence.

De petites variations de cette logique fonctionnent pour des références douces et fantômes.

La mise en œuvre est là si vous êtes vraiment curieux.

Le cache utilisant des références faibles peut ralentir considérablement votre application si elle est reconstruite à la demande, par exemple dans les getters:

 public Object getSomethingExpensiveToFind() { if(cache.contains(EXPENSIVE_OBJ_KEY)) { return cache.get(EXPENSIVE_OBJ_KEY); } Object sth = obtainSomethingExpensiveToFind(); // computationally expensive cache.put(EXPENSIVE_OBJ_KEY, sth); return sth; } 

Imaginez ce scénario:

1) l’application manque de mémoire

2) Le GC nettoie les références faibles, le cache est donc effacé aussi

3) l’application continue, beaucoup de méthodes comme getSomethingExpensiveToFind () sont appelées et reconstruisent le cache

4) l’application est à court de mémoire à nouveau

5) Le CPG nettoie les références d’usure, efface le cache

6) l’application continue, beaucoup de méthodes comme getSomethingExpensiveToFind () sont appelées et reconstruisent le cache à nouveau

7) et ainsi de suite …

Je suis tombé sur un tel problème – l’application a été interrompue par GC très souvent et elle a complètement vaincu le sharepoint la mise en cache.

En d’autres termes, si elles sont mal gérées, des références faibles peuvent ralentir votre application.