C#: Comment mettre en place une smart cache
J'ai quelques endroits où la mise en œuvre de certains sorte de cache peut être utile. Par exemple dans les cas de faire des recherches de ressources fondées sur la coutume de cordes, de trouver des noms de propriétés à l'aide de la réflexion, ou d'avoir un seul PropertyChangedEventArgs
par nom de la propriété.
Un exemple simple de cette dernière:
public static class Cache
{
private static Dictionary<string, PropertyChangedEventArgs> cache;
static Cache()
{
cache = new Dictionary<string, PropertyChangedEventArgs>();
}
public static PropertyChangedEventArgs GetPropertyChangedEventArgs(
string propertyName)
{
if (cache.ContainsKey(propertyName))
return cache[propertyName];
return cache[propertyName] = new PropertyChangedEventArgs(propertyName);
}
}
Mais, ce travail sera bien? Par exemple, si nous avons eu un tas de différents propertyNames, qui nous obligerait à la fin avec un énorme cache assis là, de ne jamais être nettoyés ou quoi que ce soit. J'imagine, si ce qui est mis en cache sont les plus grandes valeurs, et si la demande est depuis longtemps l'un, cela pourrait finir comme une sorte de problème... qu'en pensez-vous? Comment faut-il une bonne mémoire cache de mise en œuvre? Est-ce un assez bon pour la plupart des besoins? Des exemples de quelques belles implémentations de cache qui ne sont pas trop difficiles à comprendre ou trop complexe à mettre en œuvre?
- "Il y a seulement deux choses dures dans l'Informatique: l'invalidation du cache et de nommer les choses." - Phil Karlton
- Ce n'est pas la peine de l'ensemble de la réponse, mais cette mise en œuvre serait un échec spectaculaire dans un environnement multi-thread. À un strict minimum, vous avez besoin d'un verrou autour de l'accès à
cache
dansGetPropertyChangedEventArgs()
. Juste essayer d'aider quelqu'un qui arrive et la copie des pâtes à la ce.
Vous devez vous connecter pour publier un commentaire.
Vous peut encapsuler chacun de vos éléments mis en cache dans un
WeakReference
. Cela permettrait à la GC de récupérer les éléments de la si et quand nécessaire, toutefois, il ne faut pas vous donner un contrôle granulaire de lorsque les éléments vont disparaître de la mémoire cache, ou vous permettre de mettre en œuvre explicite des stratégies d'expiration etc.(Ha! Je viens de remarquer que l'exemple donné sur le Page MSDN est une simple mise en cache de la classe.)
C'est un grand problème, vous devez déterminer le domaine du problème et d'appliquer les bonnes techniques. Par exemple, comment décririez-vous l'expiration de la des objets? Elles ne deviennent obsolètes sur un intervalle fixe de temps? Elles ne deviennent obsolètes à partir d'un événement extérieur? À quelle fréquence est-ce possible? En outre, le nombre d'objets que vous avez? Enfin, combien coûte-t-il de générer l'objet?
Le plus simple serait de le faire directement memoization, comme vous l'avez ci-dessus. Cela suppose que les objets n'expirent jamais, et qu'il ne sont pas si nombreux pour exécuter votre mémoire sec et que vous pensez que le coût pour créer ces objets justifie l'utilisation d'un cache pour commencer.
La couche suivante pourrait être de limiter le nombre d'objets, et l'utilisation implicite de l'expiration de la politique, comme la LRU (moins récemment utilisé). Pour ce faire, vous devez généralement utiliser une liste doublement chaînée en plus de votre dictionnaire, et à chaque fois qu'un des objets est accessible, il est déplacé à l'avant de la liste. Alors, si vous avez besoin d'ajouter un nouvel objet, mais il est au-dessus de votre limite total d'objets, vous souhaitez supprimer à partir de la fin de la liste.
Prochaine, vous pourriez avoir besoin pour appliquer explicite d'expiration, soit basé sur le temps, ou certains stimulus externe. Il faudrait que vous avez une sorte d'expiration événement qui pourrait être appelé.
Comme vous pouvez le voir il ya beaucoup de la conception, à la mise en cache, de sorte que vous devez comprendre votre domaine et de l'ingénieur de façon appropriée. Vous n'avez pas fourni suffisamment de détails pour moi de discuter des détails, je me suis senti.
P. S. Veuillez envisager l'utilisation de Génériques lors de la définition de votre classe, de sorte que de nombreux types d'objets peuvent être stockées, permettant ainsi à votre code de mise en cache pour être réutilisé.
Ressemble .NET 4.0 prend désormais en charge du Système.Moment de l'exécution.La mise en cache pour la mise en cache de nombreux types de choses. Vous devriez regarder pour la première, au lieu de ré-inventer la roue. Plus de détails:
http://msdn.microsoft.com/en-us/library/system.runtime.caching%28VS.100%29.aspx
C'est un beau débat à avoir, mais en fonction de votre demande, voici quelques conseils:
Vous devez définir la taille maximale de la mémoire cache, que faire avec de vieux objets, si le cache est plein, avoir un nettoyage de la stratégie, de déterminer la durée de vie de l'objet dans le cache, ne cache peuvent/doivent être conservées quelque part d'autre que de la mémoire, en cas d'application en cas d'arrêt anormal, ...
Ce est un problème commun qui a beaucoup de solutions en fonction de votre application.
Il est si commun que Microsoft a publié un ensemble de la bibliothèque pour y remédier.
Vous devriez vérifier Microsoft de Vitesse avant de rouler votre propre cache.
http://msdn.microsoft.com/en-us/data/cc655792.aspx
Espérons que cette aide.
Vous pouvez utiliser un
WeakReference
mais si votre objet n'est pas aussi grand que ne le font pas parce que laWeakReference
serait de prendre plus de mémoire que l'objet lui-même qui n'est pas une bonne technique. Aussi, si l'objet est un court temps d'utilisation où il ne le fera jamais à la génération 1 de génération 0 sur la GC, il n'y a pas besoin de beaucoup pour lesWeakReference
mais interface IDisposable sur l'objet aurait avec la sortieSuppressFinalize
.Si vous voulez contrôler la durée de vie vous avez besoin d'un minuteur de mise à jour de la date/de temps encore, le desiredExpirationTime sur l'objet dans votre cache.
La chose importante est de savoir si l'objet est grand alors opter pour la WeakReference d'autre de la référence forte. Aussi, vous pouvez définir la capacité sur le Dictionnaire et de créer une file d'attente pour demander d'autres objets dans votre temp bin la sérialisation de l'objet et de le charger quand il ya de la place dans le Dictionnaire, puis l'effacer du répertoire temp.