La session de mémoire MemoryCache ou l’application est-elle étendue?

J’utilise MemoryCache dans ASP.NET et cela fonctionne bien. J’ai un object mis en cache pendant une heure pour éviter que de nouvelles données ne soient extraites du référentiel.

Je peux voir la mise en cache fonctionner dans le débogage, mais aussi une fois déployée sur le serveur, après le premier appel et que l’object est mis en cache les appels suivants sont environ 1/5 du temps.

Cependant, je remarque que chaque nouvel appel client (toujours dans cette fenêtre d’une heure – en fait une minute ou deux plus tard) semble avoir le premier appel à mon service (qui effectue la mise en cache) presque aussi longtemps que l’original. appel avant que les données aient été mises en cache.

Cela m’a fait commencer à me demander – est- MemoryCache session MemoryCache est spécifique, et chaque nouveau client qui effectue l’appel stocke son propre cache, ou est-ce que quelque chose d’autre prend si longtemps, même si je sais que les données ont été mises en cache?

De 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 les applications .NET Framework qui ne sont pas des applications ASP.NET. Par exemple, la classe MemoryCache n’a aucune dépendance sur l’assembly System.Web. Une autre différence est que vous pouvez créer plusieurs instances de la classe MemoryCache pour les utiliser dans la même application et dans la même instance AppDomain.

En lisant cela et en effectuant des recherches dans le code réfléchi, il est évident que MemoryCache n’est qu’une simple classe. Vous pouvez utiliser la propriété MemoryCache.Default pour (ré) utiliser la même instance ou vous pouvez construire autant d’instances que vous le souhaitez (bien que recommandé aussi peu que possible).

Donc, fondamentalement, la réponse réside dans votre code.
Si vous utilisez MemoryCache.Default votre cache MemoryCache.Default vie tant que votre pool d’applications est MemoryCache.Default . (Juste pour vous rappeler que le délai d’inactivité du pool d’applications par défaut est de 20 minutes, soit moins d’une heure).

Si vous le créez en utilisant le new MemoryCache(ssortingng, NameValueCollection) les considérations mentionnées ci-dessus s’ajoutent au contexte dans lequel vous créez votre instance, c’est-à-dire si vous créez votre instance dans Controller une requête

C’est dommage que je ne trouve aucune référence, mais … MemoryCache ne garantit pas la conservation des données en fonction d’une politique de cache que vous spécifiez. En particulier, si la machine sur laquelle vous exécutez votre application subit un stress en mémoire, votre cache peut être supprimé.

Si vous ne parvenez toujours pas à déterminer la raison de l’invalidation anticipée des éléments de la mémoire cache, vous pouvez tirer parti de RemoveCallback et rechercher la cause de l’invalidation des éléments.

En examinant cela un an plus tard, j’ai trouvé plus d’informations sur mon post original à propos de la mise en cache aléatoire du cache. Le MSDN indique ce qui suit pour les propriétés de cache configurables CacheMemoryLimitMegabytes et PhysicalMemoryLimitPercentage :

La valeur par défaut est 0, ce qui signifie que les heuristiques d’autosize de la classe MemoryCache sont utilisées par défaut.

En procédant à une décompilation et à une investigation, il existe des scénarios prédéterminés dans la classe CacheMemoryMonitor.cs qui définissent les seuils de mémoire. Voici un échantillon des commentaires de cette classe sur la propriété AutoPrivateBytesLimit :

 // 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 (eg console app), the 60% in the above // formulas will become 100% because in un-hosted environment we don't launch // other processes such as comstackr, etc. 

Ce n’est pas nécessairement que les valeurs spécifiques sont importantes autant que de savoir pourquoi le cache est souvent utilisé: pour stocker de gros objects que nous ne voulons pas récupérer encore et encore. Si ces objects volumineux sont stockés dans le cache et que le seuil de mémoire des environnements d’hébergement basé sur ces calculs internes est dépassé, l’élément peut être supprimé automatiquement du cache. Cela pourrait certainement expliquer mon OP car 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 existe une substitution explicite à la définition de ces valeurs. Vous pouvez via la configuration (ou lors de la configuration de l’instance MemoryCache ) définir les valeurs CacheMemoryLimitMegabytes et PhysicalMemoryLimitPercentage . Voici un exemple modifié du lien MSDN suivant, où je mets le paramètre physicalMemoryPercentage à 95 (%):