Différence entre "sur le tas" et "hors tas"


Réponses:


169

Le magasin sur le tas fait référence aux objets qui seront présents dans le tas Java (et également soumis à GC). D'autre part, le magasin hors tas fait référence aux objets (sérialisés) qui sont gérés par EHCache, mais stockés en dehors du tas (et également non soumis à GC). Comme le magasin hors tas continue d'être géré en mémoire, il est légèrement plus lent que le magasin sur tas, mais toujours plus rapide que le magasin de disques.

Les détails internes impliqués dans la gestion et l'utilisation du magasin hors tas ne sont pas très évidents dans le lien publié dans la question, il serait donc sage de vérifier les détails de Terracotta BigMemory , qui est utilisé pour gérer le hors-disque boutique. BigMemory (le magasin hors tas) doit être utilisé pour éviter la surcharge de GC sur un tas de plusieurs mégaoctets ou gigaoctets. BigMemory utilise l'espace d'adressage mémoire du processus JVM, via des ByteBuffers directs qui ne sont pas soumis à GC contrairement aux autres objets Java natifs.


18
+1 pour mentionner les ByteBuffers directs pour une exploration plus approfondie;)
Max

3
Les ByteBuffers directs offrent un accès à la mémoire non gérée, mais sont eux-mêmes soumis à GC (par opposition aux données vers lesquelles ils pointent). Ceci est important car un ByteBuffer direct (le type ByteBuffer.allocateDirect, pas le type MMap) sera collecté par le GC et lorsqu'il sera collecté, Deallocater sera déclenché, collectant également efficacement la mémoire non gérée.
Nitsan Wakart

L'utilisation de Unsafe pour allouer des objets semble avoir des performances de lecture et d'écriture nettement meilleures sur Onheap / DirectByteBuffers / ByteBuffers. ashkrit.blogspot.com/2013/07/…
Joe C

98

depuis http://code.google.com/p/fast-serialization/wiki/QuickStartHeapOff

Qu'est-ce que le déchargement de tas?

Habituellement, tous les objets non temporaires que vous allouez sont gérés par le garbage collector de java. Bien que la VM fasse un travail décent en effectuant un garbage collection, à un certain moment, la VM doit faire un soi-disant «GC complet». Un GC complet implique l'analyse du tas alloué complet, ce qui signifie que les pauses / ralentissements du GC sont proportionnels à la taille du tas d'applications. Alors ne faites confiance à personne qui vous dit «La mémoire est bon marché». En java, la consommation de mémoire nuit aux performances. De plus, vous pouvez obtenir des pauses notables en utilisant des tailles de tas> 1 Go. Cela peut être désagréable si vous avez des choses en temps quasi réel, dans un cluster ou une grille, un processus java peut ne plus répondre et être supprimé du cluster.

Cependant, les applications serveur d'aujourd'hui (souvent construites sur des frameworks gonflés ;-)) nécessitent facilement des tas bien au-delà de 4 Go.

Une solution à ces besoins en mémoire consiste à «décharger» des parties des objets vers le tas non java (directement alloué à partir du système d'exploitation). Heureusement, java.nio fournit des classes pour allouer / lire et écrire directement des morceaux de mémoire «non gérés» (même des fichiers mappés en mémoire).

Ainsi, on peut allouer de grandes quantités de mémoire «non gérée» et l'utiliser pour y enregistrer des objets. Afin d'enregistrer des objets arbitraires dans une mémoire non gérée, la solution la plus viable est l'utilisation de la sérialisation. Cela signifie que l'application sérialise les objets dans la mémoire offheap, plus tard, l'objet peut être lu à l'aide de la désérialisation.

La taille du tas gérée par la VM java peut être réduite, donc les pauses GC sont dans les millisecondes, tout le monde est content, le travail est fait.

Il est clair que les performances d'un tel tampon hors tas dépendent principalement des performances de l'implémentation de la sérialisation. Bonne nouvelle: pour une raison quelconque, la sérialisation FST est assez rapide :-).

Exemples de scénarios d'utilisation:

  • Cache de session dans une application serveur. Utilisez un fichier mappé en mémoire pour stocker des gigaoctets de sessions utilisateur (inactives). Une fois que l'utilisateur se connecte à votre application, vous pouvez accéder rapidement aux données relatives à l'utilisateur sans avoir à gérer une base de données.
  • Mise en cache des résultats de calcul (requêtes, pages html, ..) (applicable uniquement si le calcul est plus lent que la désérialisation de l'objet résultat ofc).
  • persistance très simple et rapide à l'aide de fichiers mappés en mémoire

Edit: Pour certains scénarios, on peut choisir des algorithmes de récupération de place plus sophistiqués tels que ConcurrentMarkAndSweep ou G1 pour prendre en charge des tas plus volumineux (mais cela a également ses limites au-delà de 16 Go de tas). Il existe également une JVM commerciale avec un GC amélioré «sans pause» (Azul).


4
«allouez de grandes quantités de mémoire« non gérée »et utilisez-la pour y enregistrer des objets» - vous ne pouvez pas enregistrer les objets hors du tas. Vous pouvez stocker des primitives, vous pouvez les envelopper dans la bibliothèque de votre choix, mais ce ne sont pas des objets. Les données que vous placez hors du tas n'ont pas d'en-tête d'objet, vous ne pouvez pas vous synchroniser dessus, vous ne pouvez pas y faire référence avec un champ de référence dans un autre objet.
Nitsan Wakart

41

Le tas est l'endroit en mémoire où vivent vos objets alloués dynamiquement. Si vous avez utilisé, newc'est sur le tas. C'est par opposition à l'espace de pile, où réside la pile de fonctions. Si vous avez une variable locale, cette référence se trouve sur la pile. Le tas de Java est soumis au garbage collection et les objets sont utilisables directement.

Le stockage hors tas d'EHCache retire votre objet normal du tas, le sérialise et le stocke sous forme d'octets dans un bloc de mémoire géré par EHCache. C'est comme le stocker sur disque mais il est toujours en RAM. Les objets ne sont pas directement utilisables dans cet état, ils doivent d'abord être désérialisés. Également non soumis à la collecte des ordures.


N'est-il pas simplement toujours dans le tas mais sous une forme sérialisée?
Pacerier

1
comment cela le rend-il plus efficace?
Pacerier

2
Il y a beaucoup de façons. Puisque les objets ne sont plus sur le tas Java principal, ils ne gaspillent pas le temps du ramasse-miettes, ils ne fragmentent pas le tas de la JVM et ils libèrent de l'espace pour d'autres objets plus utilisés. De plus, comme ils sont sérialisés et probablement pas nécessaires dans un avenir immédiat, ils peuvent être compressés, déplacés selon les besoins ou même paginés sur le disque.
Adam

1
Dans Hotspot, le temps de pause du GC dépend directement de la taille du tas. BigMemory offre ce compromis en utilisant la RAM au lieu du tas, pour maintenir la pause GC au minimum et éviter le coût IO de l'accès au disque.
Chander Shivdasani


1

La JVM ne sait rien de la mémoire hors tas. Ehcache implémente un cache sur disque ainsi qu'un cache en mémoire.


1

Pas à 100%; cependant, il semble que le tas soit un objet ou un ensemble d'espace alloué (sur la RAM) qui est intégré à la fonctionnalité du code soit Java lui-même, soit une fonctionnalité plus probable d'ehcache lui-même, et le Ram hors tas est son propre système en tant que bien; cependant, il semble que ce soit une magnitude plus lent car il n'est pas aussi organisé, ce qui signifie qu'il peut ne pas utiliser un tas (ce qui signifie un long ensemble d'espace de RAM), et utilise à la place différents espaces d'adressage le rendant probablement légèrement moins efficace.

Ensuite, bien sûr, le niveau inférieur suivant est l'espace du disque dur lui-même.

Je n'utilise pas ehcache, donc vous ne voudrez peut-être pas me faire confiance, mais c'est ce que j'ai recueilli à partir de leur documentation.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.