Comment puis-je efficacement en cache les objets en Java à l'aide de la RAM disponible?
J'ai besoin de cache d'objets en Java en utilisant une proportion de ce que la RAM est disponible. Je suis conscient que d'autres ont posé cette question, mais aucune des réponses répondre à mes exigences.
Mes besoins sont:
- Simple et léger
- Pas considérablement plus lent qu'un simple HashMap
- Utilisation LRU, ou de certains de la politique de suppression qui se rapproche de la LRU
J'ai essayé LinkedHashMap, cependant il vous demande de spécifier un nombre maximum d'éléments, et je ne sais pas combien d'éléments qu'il faudra pour remplir la RAM disponible (leurs tailles varient de façon significative).
Mon approche actuelle est d'utiliser Google Collecte du Cartographe comme suit:
Map<String, Object> cache = new MapMaker().softKeys().makeMap();
Cela semble attrayant comme il se doit supprimer automatiquement les éléments lorsqu'il a besoin de plus de RAM, il y a cependant un problème de taille: son comportement est de remplir toute la mémoire disponible, à quel point le GC commence à le thrash et l'ensemble de l'application du rendement se détériore considérablement.
J'ai entendu des trucs comme EHCache, mais il semble assez lourd pour ce dont j'ai besoin, et je ne suis pas sûr si il est assez rapide pour mon application (en se souvenant que la solution ne peut pas être considérablement plus lent que d'une table de hachage).
- quels types d'objets sont vous la mise en cache? Je ne suis pas tout à fait pourquoi vous êtes inquiet au sujet de la performance de la mémoire cache, en considérant que dès que vous êtes à l'expiration de la politique, vous allez engager plus de ressources qu'une simple Carte et EHCache est bien développé de la mise en cache lib, qui (je pense configuré à l'aide de Printemps ici) n'est pas complexe et tout aussi simple à utiliser qu'une carte.
- Les objets varient en taille de 1 à peut-être 10kbs. Je suis inquiet au sujet de la performance en raison de la récupération d'objets dans le cache est dans la boucle interne de beaucoup de temps CPU du processus. Si il est lent, il peut augmenter le temps nécessaire pour que mon appli pour faire sa chose à partir de quelques minutes à quelques heures.
- Avec les touches() vous n'obtiendrez pas un hit si vous utilisez equals(), vous obtiendrez seulement un coup si vous êtes à la recherche de l'objet avec référence à l'égalité. Si vous avez besoin d'equals() pour le cache, puis utilisez softValues() à la place.
- Double Possible de Facile, simple à utiliser LRU cache en java
Vous devez vous connecter pour publier un commentaire.
J'ai des exigences semblables à vous - de la concurrence (sur 2 hexacore Cpu) et de la loi LRU ou similaire - et j'ai aussi essayé de Goyave Cartographe. J'ai trouvé softValues() beaucoup plus lent que weakValues(), mais tous les deux fait mon application désespérément lente lorsque la mémoire rempli.
J'ai essayé WeakHashMap et c'est moins problématique, bizarrement, même plus rapide que d'utiliser LinkedHashMap comme un cache LRU par l'intermédiaire de son removeEldestEntry() la méthode.
Mais par la manière la plus rapide pour moi, c'est ConcurrentLinkedHashMap qui a fait de mon app 3-4 (!!) fois plus rapide que n'importe quel autre cache, j'ai essayé. Joie, après des jours de frustration! C'est apparemment été incorporées dans la Goyave est Cartographe, mais la LRU, la fonctionnalité n'est pas dans la Goyave r07 à toute vitesse. Espérons que cela fonctionne pour vous.
J'ai mis en place serval caches et c'est probablement aussi difficile que la mise en œuvre d'une nouvelle source de données ou de pool de threads, ma recommandation est d'utiliser jboss-cache ou un autre bien connu de la mise en cache lib.
Donc, vous permettra de bien dormir sans problèmes
Je ne sais vraiment pas si l'on peut dire que EHCache est poids lourds. Au moins, je ne considère pas EHCache en tant que tel, en particulier lors de l'utilisation d'un Mémoire De (qui est soutenu par une longue
LinkedHashMap
et est bien sûr le plus rapide de l'option de mise en cache). Vous devez lui donner un essai.Je crois
MapMaker
est le seul moyen raisonnable d'obtenir ce que vous demandez. Si "le GC commence à le thrash et l'ensemble de l'application du rendement se détériore considérablement," vous devriez passer un peu de temps définissant correctement les différents paramètres de réglage. Ce document peut sembler un peu intimidant au début, mais c'est écrit très clairement et est une mine d'or d'informations utiles sur GC:http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf
Je ne sais pas si ce serait une solution simple, surtout par rapport à la EHCache ou similaire, mais avez-vous regardé le Javolution bibliothèque? Il n'est pas conçu comme tel, mais dans le
javolution.context
package, ils ont un Allocateur de modèle qui puisse réutiliser les objets sans la nécessité pour la collecte des ordures. De cette façon, ils gardent la création de l'objet et la collecte des déchets à un minimum, une caractéristique importante pour la programmation en temps réel. Peut-être que vous devriez jeter un oeil et essayer de l'adapter à votre problème.À l'aide de touches de fonction permet tout simplement le garbage collector de supprimer des objets du cache lorsque aucun autre objet de référence (i.e., lorsque la seule chose que se référant à la clé de cache, le cache lui-même). Il ne garantit pas de toute autre sorte d'expulsion.
La plupart des solutions que vous trouverez seront ajoutés sur le dessus de la java de la Carte des classes, y compris EhCache.
Avez-vous regardé le commons-collections LRUMap?
Noter qu'il existe une question ouverte contre Cartographe de fournir LRU/MRU fonctionnalité. Peut-être vous pouvez exprimer votre opinion, il y a l'
À l'aide de votre cache, magasin WeakReference plutôt que la normale objet refererences.
Si GC commence à manquer d'espace libre, les valeurs détenues par WeakReferences sera libéré.
SoftReference
- faiblement les objets référencés peuvent être récupérés à tout moment, sans aucun égard pour libérer de la mémoire.Dans le passé, j'ai utilisé JCS. Vous pouvez configurer le configuration pour tenter de répondre à vous besoins. Je ne sais pas si cela va répondre à tous vos besoins/besoins, mais je trouve qu'il est assez puissant quand je l'ai utilisé.
Vous ne pouvez pas "supprimer des éléments" vous ne pouvez arrêter de dur de référence et attendre que la GC pour les nettoyer, alors, allez sur Google Collections...
Je ne suis pas au courant d'une façon facile de trouver un objet de la taille en Java. Donc, je ne pense pas que vous trouverez un moyen de limiter une structure de données par la quantité de RAM c'est prenant.
Basé sur cette hypothèse, vous êtes coincé avec le limiter par le nombre d'objets mis en cache. Je vous suggère de l'exécution de simulations de quelques de la vie réelle des scénarios d'utilisation et la collecte de statistiques sur les types d'objets qui vont dans le cache. Ensuite, vous pouvez calculer statistiquement de taille moyenne, et le nombre d'objets que vous pouvez vous permettre de cache. Même si c'est seulement une approximation de la quantité de RAM que vous souhaitez consacrer à la cache, il pourrait être assez bon.
Comme pour le cache de mise en œuvre, dans mon projet (la performance des applications critiques) nous sommes à l'aide de EhCache, et personnellement je ne trouve pas qu'il soit lourd à tous.
Dans tous les cas, exécuter plusieurs tests avec plusieurs configurations différentes (sur la taille, l'expulsion de la politique, etc.) et de trouver ce qui fonctionne le mieux pour vous.
Cache quelque chose,
SoftReference
peut-être la meilleure façon jusqu'à maintenant, je peux imaginer.Ou vous pouvez réinventer un Objet de la piscine. Que chaque objet que vous n'utilisez pas, vous n'avez pas besoin de les détruire. Mais pour économiser du CPU plutôt que d'économiser de la mémoire
En supposant que vous voulez le cache pour être thread-safe, alors vous devriez examiner le cache exemple de Brian Goetz du livre "Java Simultanéité dans la Pratique". Je ne peux pas recommander cette très suffisant.