Amélioration des performances avec des mappes de tableaux d'octets

Vous pouvez stocker les valeurs de vos mappes dans un tableau d'octets plutôt que dans un formulaire POJO pour réduire la consommation de mémoire d'un graphique d'objets de grande taille.

Avantages

La quantité de mémoire nécessaire augmente avec le nombre d'objets d'un graphe. Lorsque vous réduisez un graphe complexe à un tableau d'octets, un seul objet est conservé dans le segment de mémoire, et non plusieurs. L'environnement d'exécution Java exécute ses recherches dans un nombre réduit d'objets lors de la récupération de place.

Le mécanisme de copie par défaut utilisé par WebSphere eXtreme Scale est la sérialisation, qui est un mécanisme coûteux. Si, par exemple, vous utilisez le mode de copie par défaut COPY_ON_READ_AND_COMMIT, une copie est faite au moment de la lecture et au moment de l'extraction. Avec un tableau d'octets, la valeur augmente en raison du nombre d'octets, mais aucune copie n'est exécutée au moment de la lecture, et la valeur est sérialisée en plusieurs octets, mais aucune copie n'est exécutée au moment de l'extraction. L'utilisation des tableaux d'octets résulte en une cohérence des données équivalente à celle qui serait obtenue avec le paramètre par défaut, mais en réduisant la mémoire utilisée.

Notez qu'un mécanisme de sérialisation optimisé est indispensable pour pouvoir constater une réduction de la mémoire consommée dans le cadre de l'utilisation des tableaux d'octets. Pour plus d'informations, voir Optimisation des performances de sérialisation.

Configuration des mappes de tableaux d'octets

Vous pouvez activer les mappes de tableaux d'octets à l'aide du fichier XML ObjectGrid et en associant l'attribut CopyMode utilisé par une mappe au paramètre COPY_TO_BYTES, comme dans l'exemple suivant :

<backingMap name="byteMap" copyMode="COPY_TO_BYTES" />

Considérations

Vous devez réfléchir à l'éventuelle utilisation des mappes de tableaux d'octets dans un scénario donné. Même si celle-ci doit vous permettre de réduire la consommation de mémoire, l'utilisation du processeur risque d'augmenter.

La liste suivante recense les différents facteurs à prendre en compte avant d'opter pour l'utilisation de la fonction de mappes de tableaux d'octets.

Type de l'objet

Avec certains types d'objet, les mappes de tableaux d'octets ne permettent pas de réduire la consommation de mémoire. Il existe donc certains types d'objets pour lesquels l'utilisation de ces mappes n'est pas recommandée. Si vous utilisez comme valeur des encapsuleurs primitifs Java ou un objet Java simple ne contenant aucune référence à d'autres objets (se contentant de stocker des zones primitifs), le nombre d'objets Java est déjà aussi peu élevé que possible : il se limite à un. La quantité de mémoire utilisée par cet objet étant déjà optimisée, l'utilisation d'une mappe de tableaux d'octets n'est pas recommandée. Ce type de mappes convient mieux aux types d'objets contenant d'autres objets ou collections d'objets dans lesquels le nombre total d'objets simples Java est supérieur à un.

Par exemple, dans le cas d'un objet Customer associé à une adresse professionnelle, à une adresse personnelle et à une collection de commandes, vous pouvez réduire le nombre d'objets du segment de mémoire et le nombre d'octets utilisés par ces objets à l'aide des mappes de tableaux d'octets.

Adresse locale

Lorsque vous utilisez d'autres modes de copie, vous pouvez optimiser les applications lors des copies si les objets sont clonables avec l'ObjectTransformer par défaut ou lorsqu'un ObjectTransformer personnalisé est fourni avec une méthode copyValue optimisée. Par rapport aux autres modes de copie, le coût des copies des opérations de lecture, d'écriture ou de validation est supérieur lorsque l'accès aux objets se fait localement. Si, par exemple, un cache local existe dans une topologie répartie ou que vous accédiez directement à une instance ObjectGrid locale ou de serveur, la durée d'accès et de validation augmentent en cas d'utilisation des mappes de tableaux d'octets du fait du coût de la sérialisation. Dans le même type de topologie, ce coût augmente également si vous utilisez de agents de grille de données ou si vous accédez au serveur principalement lorsque vous utilisez le plug-in ObjectGridEventGroup.ShardEvents.

Interactions des plug-in

Avec les mappes de tableaux d'octets, les objets n'augmentent pas lors de la communication d'un client à un serveur, à moins que le serveur n'ait besoin du formulaire d'objet Java simple. Les plug-in qui interagissent avec la valeur de la mappe vont connaître une réduction de leurs performances en raison de l'augmentation nécessaire de la valeur.

Les plug-in utilisant LogElement.getCacheEntry ou LogElement.getCurrentValue devront subir ce coût supplémentaire. Si vous souhaitez obtenir la clé, vous pouvez utiliser LogElement.getKey, qui permet d'éviter les frais supplémentaires associés à la méthode LogElement.getCacheEntry().getKey. Les sections suivantes décrivent les plug-in dans le contexte de l'utilisation des tableaux d'octets.

Index et requêtes

Lorsque des objets sont stockés au format objet Java simple, le coût de l'indexation et de l'interrogation est minime car l'objet n'a pas besoin d'être augmenté. Lorsque vous utilisez une mappe de tableau d'objets, vous devez subir un coût supplémentaire lié à l'augmentation de l'objet. En général, si votre application utilise des index ou des requêtes, nous ne vous recommandons pas d'utiliser les mappes de tableaux d'octets, à moins que vous exécutiez uniquement des requêtes sur les attributs clés.

Verrouillage optimiste

Lorsque vous utilisez la stratégie de verrouillage optimiste, vous devrez subir un coût supplémentaire lors des opérations de mise à jour et d'invalidation. Vous devez en effet augmenter la valeur du serveur pour obtenir la valeur de la version permettant une vérification de la collision optimiste. Si vous utilisez le verrouillage optimiste uniquement pour garantir les opérations d'extraction, mais que vous n'ayez pas besoin de la vérification de collision optimiste, vous pouvez utiliser com.ibm.websphere.objectgrid.plugins.builtins.NoVersioningOptimisticCallback pour désactiver la vérification de la version.

Chargeur

Avec un chargeur, vous devez également subir le coût lié à l'augmentation et à la resérialisation de la valeur. Vous pouvez cependant utiliser les mappes de tableaux d'octets avec un chargeur, mais vous devez prendre en compte le coût des modifications à apporter dans ce genre de scénario. Vous pouvez par exemple utiliser la fonction de tableau d'octets dans le contexte d'un cache qui est principalement lu. Dans ce cas, l'avantage lié à un nombre réduit d'objets dans le segment de mémoire et à une utilisation moindre de la mémoire compense la perte provoquée par l'utilisation des tableaux d'octets pour les opérations d'insertion et de mise à jour.

ObjectGridEventListener

Lorsque vous utilisez la méthode transactionEnd dans le plug-in ObjectGridEventListener, vous devez supporter un coût supplémentaire côté serveur pour les demandes distantes lors de l'accès à un CacheEntry de LogElement ou à la valeur en cours. Si l'implémentation de la méthode n'accède pas à ces zones, ce coût supplémentaire n'est pas généré.