Les systèmes d'exploitation effectuent des opérations d'E / S sur les zones de mémoire. Ces zones de mémoire, en ce qui concerne le système d'exploitation, sont des séquences d'octets contiguës. Il n'est donc pas surprenant que seuls les tampons d'octets soient éligibles pour participer aux opérations d'E / S. Rappelons également que le système d'exploitation accédera directement à l'espace d'adressage du processus, dans ce cas le processus JVM, pour transférer les données. Cela signifie que les zones de mémoire qui sont les cibles des opérations d'E / S doivent être des séquences d'octets contiguës. Dans la JVM, un tableau d'octets peut ne pas être stocké de manière contiguë en mémoire ou le garbage collector peut le déplacer à tout moment. Les tableaux sont des objets en Java, et la façon dont les données sont stockées dans cet objet peut varier d'une implémentation JVM à une autre.
Pour cette raison, la notion de tampon direct a été introduite. Les tampons directs sont destinés à l'interaction avec les canaux et les routines d'E / S natives. Ils font de leur mieux pour stocker les éléments d'octets dans une zone de mémoire qu'un canal peut utiliser pour un accès direct ou brut en utilisant du code natif pour indiquer au système d'exploitation de drainer ou de remplir la zone de mémoire directement.
Les tampons d'octets directs sont généralement le meilleur choix pour les opérations d'E / S. De par leur conception, ils prennent en charge le mécanisme d'E / S le plus efficace disponible pour la JVM. Les tampons d'octets non directs peuvent être passés aux canaux, mais cela peut entraîner une baisse des performances. Il n'est généralement pas possible qu'un tampon non direct soit la cible d'une opération d'E / S native. Si vous passez un objet ByteBuffer non direct à un canal pour l'écriture, le canal peut implicitement effectuer les opérations suivantes à chaque appel:
- Créez un objet ByteBuffer direct temporaire.
- Copiez le contenu du tampon non direct dans le tampon temporaire.
- Effectuez l'opération d'E / S de bas niveau à l'aide du tampon temporaire.
- L'objet tampon temporaire est hors de portée et est finalement récupéré.
Cela peut potentiellement entraîner une copie de la mémoire tampon et une rotation des objets sur chaque E / S, ce qui est exactement le genre de choses que nous aimerions éviter. Cependant, selon l'implémentation, les choses peuvent ne pas être si mauvaises. Le moteur d'exécution mettra probablement en cache et réutilisera les tampons directs ou effectuera d'autres astuces intelligentes pour augmenter le débit. Si vous créez simplement un tampon pour une utilisation unique, la différence n'est pas significative. D'un autre côté, si vous allez utiliser le tampon à plusieurs reprises dans un scénario hautes performances, il vaut mieux allouer des tampons directs et les réutiliser.
Les tampons directs sont optimaux pour les E / S, mais ils peuvent être plus coûteux à créer que les tampons d'octets non directs. La mémoire utilisée par les tampons directs est allouée en appelant du code natif spécifique au système d'exploitation, en contournant le tas JVM standard. Selon le système d'exploitation hôte et l'implémentation de la JVM, la configuration et la suppression de tampons directs peuvent être beaucoup plus coûteux que les tampons résidents du tas. Les zones de stockage en mémoire des tampons directs ne sont pas soumises au nettoyage de la mémoire car elles sont en dehors du tas JVM standard.
Les compromis en termes de performances entre l'utilisation de tampons directs et non directs peuvent varier considérablement selon la JVM, le système d'exploitation et la conception du code. En allouant de la mémoire en dehors du tas, vous pouvez soumettre votre application à des forces supplémentaires dont la JVM n'a pas connaissance. Lorsque vous mettez en jeu des pièces mobiles supplémentaires, assurez-vous d'obtenir l'effet souhaité. Je recommande l'ancienne maxime du logiciel: faites-le d'abord fonctionner, puis faites-le rapidement. Ne vous inquiétez pas trop de l'optimisation à l'avance; concentrez-vous d'abord sur l'exactitude. L'implémentation JVM peut être en mesure d'effectuer la mise en cache de la mémoire tampon ou d'autres optimisations qui vous donneront les performances dont vous avez besoin sans trop d'efforts inutiles de votre part.