web-dev-qa-db-fra.com

Utilisation de plusieurs instances de MemoryCache

Je voudrais ajouter des capacités de mise en cache à mon application en utilisant le System.Runtime.Caching namespace, et voudrait probablement utiliser la mise en cache à plusieurs endroits et dans différents contextes. Pour ce faire, je souhaite utiliser plusieurs instances de MemoryCache.

Cependant, je vois ici que l'utilisation de plusieurs instances de MemoryCache est déconseillée:

MemoryCache n'est pas un singleton, mais vous ne devez créer que quelques ou potentiellement une seule instance MemoryCache et du code qui met en cache les éléments qui doivent utiliser ces instances.

Comment plusieurs instances MemoryCache affectent-elles mon application? Je trouve ce genre de bizarre, car il me semble que l'utilisation de plusieurs caches dans une application est un scénario assez courant.

EDIT: Plus précisément, j'ai une classe qui devrait garder un cache pour chaque instance. Dois-je éviter d'utiliser MemoryCache et rechercher une autre solution de mise en cache? L'utilisation de MemoryCache dans cette situation est-elle considérée comme mauvaise, et si oui, pourquoi?

67
Adi Lester

J'ai récemment vécu cela moi aussi. Étant donné qu'un cache en mémoire sera spécifique au processus (non partagé entre plusieurs instances d'un site Web ou d'une application métier native ou plusieurs serveurs), il n'y a vraiment aucun avantage à avoir plusieurs instances MemoryCache sauf pour des raisons d'organisation du code (qui peuvent être obtenus par d’autres moyens).

Le cache mémoire est destiné à être utilisé seul principalement en raison de ses capacités de gestion de la mémoire. En plus des compteurs de performances (qui ont une certaine surcharge), le MemoryCache est également en mesure d'expiration des éléments lorsqu'il manque de mémoire allouée.

Si l'instance actuelle du cache dépasse la limite de mémoire définie par la propriété CacheMemoryLimit, l'implémentation du cache supprime les entrées de cache. Chaque instance de cache de l'application peut utiliser la quantité de mémoire spécifiée par la propriété CacheMemoryLimit.

de propriété MemoryCache.CacheMemoryLimit

En utilisant une seule instance de MemoryCache, il peut appliquer efficacement cette gestion de la mémoire à l'ensemble de l'instance d'application. Expiration des éléments les moins importants sur l'ensemble de l'application. Cela garantit une utilisation maximale de la mémoire, sans dépasser vos capacités matérielles. En limitant la portée de n'importe quel MemoryCache (comme à une instance d'une classe), il ne peut plus gérer efficacement la mémoire de votre application (car il ne peut pas "tout voir"). Si tous ces caches étaient "occupés", vous pourriez avoir plus de mal à gérer la mémoire et ce ne serait jamais aussi efficace.

Ceci est particulièrement sensible dans les applications qui n'ont pas le luxe d'un serveur dédié. Imaginez que vous exécutez votre application sur un serveur partagé où vous n'avez été alloué que 150 Mo RAM (hébergement ordinaire bon marché de 10 $/mois), vous devez compter sur votre cache pour l'utiliser au maximum sans Si vous dépassez cette utilisation de la mémoire, votre pool d'applications sera recyclé et votre application perdra tous les caches de mémoire! (pratique d'hébergement bon marché courante) La même chose pourrait s'appliquer à une application non Web hébergée en interne sur un serveur d'entreprise partagé. accord, on vous dit de ne pas monopoliser toute la mémoire de cette machine et de coexister pacifiquement avec une autre application métier.

Cette limite de mémoire, le recyclage du pool d'applications, la perte de caches est un "talon d'Achille" commun aux applications Web. Lorsque les applications sont les plus occupées, elles se réinitialisent le plus souvent en raison du dépassement des allocations de mémoire, de la perte de toutes les entrées de cache et, par conséquent, de la récupération la plus importante qui aurait dû être mise en cache en premier lieu. Cela signifie que l'application perd en fait les performances à la charge maximale au lieu de gagner.

Je sais que MemoryCache est la version non Web spécifique de l'implémentation de System.Web.Caching.Cache, mais cela illustre la logique derrière l'implémentation du cache. La même logique peut s'appliquer dans un projet non Web si vous n'avez pas l'utilisation exclusive du matériel. N'oubliez pas que si votre cache force la machine à commencer à effectuer des échanges de fichiers d'échange, votre cache n'est plus plus rapide que la mise en cache sur disque. Vous voudrez toujours une limite quelque part, même si cette limite est de 2 Go ou quelque chose.

Dans mon cas, après avoir lu à ce sujet, je suis passé à l'utilisation d'un "MemoryCache statique public" dans mon application et j'ai simplement séparé les éléments mis en cache par leurs clés de cache. Par exemple, si vous souhaitez mettre en cache sur une instance, vous pouvez avoir une clé de cache comme quelque chose comme "instance- {instanceId} -resourceName- {resourceId}". Considérez-le comme un espacement de nom de vos entrées de cache.

J'espère que cela pourra aider!

65
BenSwayne

J'en utilise plusieurs aussi. Généralement un par type.

En regardant le MemoryCache, je vois qu'il se connecte aux événements AppDomain et maintient des compteurs de performances. Je soupçonne alors qu'il y a des frais supplémentaires en termes de ressources en utilisant plus d'un (par exemple CPU, compteurs et mémoire) et c'est pourquoi cela est déconseillé.

6
Kit