MemoryCache scope session ou application wide?

j'utilise MemoryCache dans ASP.NET et ça marche bien. J'ai un objet est mis en cache pour une heure afin de prévenir frais tire de données du référentiel.

je peux voir la mise en cache fonctionner dans le debug, mais aussi une fois déployé sur le serveur, après le premier appel est fait et l'objet est mis en cache les appels suivants sont environ 1/5 du temps.

Cependant, je m'aperçois que chaque appel du client (toujours à l'intérieur de cette fenêtre d'une heure - en fait, juste une minute ou deux plus tard) semble avoir le premier appel à mon service (c'est-à-dire faire la mise en cache) prenant presque aussi longtemps que l'appel original avant que les données ne soient mises en cache.

Cela m'a fait commencer à se demander - est MemoryCache session spécifique, et chaque nouveau client de faire l'appel pour l'enregistrement de son propre cache, ou quelque chose d'autre à faire de cause le 1er appel à prendre si longtemps encore après je sais que les données ont été mises en cache?

41
demandé sur John Saunders 2013-05-22 00:28:01

2 réponses

MSDN:

les principales différences entre les classes Cache et MemoryCache sont: que la classe MemoryCache a été modifiée pour la rendre utilisable par .NET Applications cadres qui ne sont pas ASP.NET applications. Exemple, la classe MemoryCache n'a pas de dépendances sur le système.Web de l'assemblée. Une autre différence est que vous pouvez créer plusieurs instances de la MemoryCache class pour une utilisation dans la même application et dans la même Domaine d'application instance.

en lisant cela et en faisant quelques recherches dans le code reflété il est évident que MemoryCache est juste un cours simple. Vous pouvez utiliser MemoryCache.Default propriété à (ré)utiliser la même instance ou vous pouvez créer autant d'instances que vous voulez (bien que recommandé est aussi peu que possible).

donc la réponse se trouve essentiellement dans votre code.

Si vous utilisez MemoryCache.Default alors votre cache vit aussi longtemps que votre pool d'applications vit. (Juste pour vous rappeler que par défaut le temps d'arrêt de la piscine d'application est de 20 minutes, soit moins d'une heure.)

si vous le Créez en utilisant new MemoryCache(string, NameValueCollection) puis les considérations ci-dessus s'appliquent plus le contexte dans lequel vous créez votre instance, c'est-à-dire si vous créez votre instance à l'intérieur du controller (ce qui, je l'espère, n'est pas le cas) alors votre cache vit pour une requête

C'est dommage que je ne trouve pas de références, mais ... MemoryCache ne garantit pas à contenir les données selon une politique de cache que vous spécifiez. Notamment si la machine sur laquelle vous lancez votre application est stressée en mémoire, votre cache pourrait être abandonné.

si vous n'avez toujours pas de chance de trouver quelle est la raison de l'invalidation anticipée d'un élément de cache, vous pouvez profiter de RemoveCallback et rechercher quelle est la raison de l'invalidation de l'article.

65
répondu Ramunas 2013-05-22 10:29:52

en passant cela en revue un an plus tard, j'ai trouvé plus d'informations sur mon post original sur le cache 'largage' au hasard. Le MSDN indique ce qui suit pour les propriétés configurables du cache CacheMemoryLimitMegabytes et PhysicalMemoryLimitPercentage:

la valeur par défaut est 0, ce qui signifie que la classe MemoryCache autosize heuristics sont utilisés par défaut.

faisant un peu de décompilage et d'enquête, il y a des scénarios prédéterminés profondément dans le CacheMemoryMonitor.cs classe définir les seuils de mémoire. Voici un échantillon des commentaires de cette classe sur le AutoPrivateBytesLimit propriété:

// Auto-generate the private bytes limit:
// - On 64bit, the auto value is MIN(60% physical_ram, 1 TB)
// - On x86, for 2GB, the auto value is MIN(60% physical_ram, 800 MB)
// - On x86, for 3GB, the auto value is MIN(60% physical_ram, 1800 MB)
//
// - If it's not a hosted environment (e.g. console app), the 60% in the above
//   formulas will become 100% because in un-hosted environment we don't launch
//   other processes such as compiler, etc.

ce n'est pas nécessairement le certains les valeurs sont aussi importantes que de comprendre pourquoi le cache est souvent utilisé: stocker grand objets que nous ne voulons pas aller chercher plus et plus. Si ces grand les objets sont stockés dans le cache et le seuil de mémoire des environnements d'hébergement basé sur ces calculs internes sont dépassés, vous pouvez avoir l'élément retiré du cache automatiquement. Cela pourrait certainement expliquer mon OP parce que je stockais une très grande collection en mémoire sur un serveur hébergé avec probablement 2 Go de mémoire exécutant plusieurs applications dans IIS.

il y a une option explicite pour définir ces valeurs. Vous pouvez via la configuration (ou lors de la mise en place du MemoryCache exemple) définissez CacheMemoryLimitMegabytes et PhysicalMemoryLimitPercentage valeurs. Voici un échantillon modifié de ce qui suit: MSDN lien où j'ai mis le physicalMemoryPercentage à 95 (%):

<configuration>
  <system.runtime.caching>
    <memoryCache>
      <namedCaches>
          <add name="default" 
               physicalMemoryLimitPercentage="95" />
      </namedCaches>
    </memoryCache>
  </system.runtime.caching>
</configuration>
22
répondu atconway 2018-08-24 00:00:40