2012-04-03 13 views
17

Ich habe eine Website, wo ich eine Menge Informationen zwischenspeichern. Ich sehe widersprüchliche Informationen zum Speichern von Inhalten im asp.net-Cache.Was ist der effizienteste Weg zum Speichern/Abrufen von Elementen in asp.net httpContext.Cache

Zum Beispiel kann sagen, dass ich diese Datenstruktur:

Dictionary<string, List<Car>> mydictionary; 

Ich konnte die ganze Sache mit einem String-Schlüssel als „MyDictionary“ speichern und dann einen Drilldown, sobald ich das Objekt herausziehen.

HttpContext.Cache.Add("MyDictionary", 
    mydictionary, 
    null, 
    Cache.NoAbsoluteExpiration, 
    new TimeSpan(10, 0, 0), 
    CacheItemPriority.Normal, 
    null); 

var myDict = HttpContext.Cache["MyDictionary"] as Dictionary<string, List<Car>>; 

Das andere, was ich tun könnte, ist es brechen und speichern Sie jedes Element in meinem Wörterbuch separat im Cache (angesichts der Cache ist ein Wörterbuch sowieso).

Dictionary<string, List<Car>> mydictionary; 

foreach (var item in mydictionary.Keys) 
{ 
     HttpContext.Cache.Add(item, mydictionary[item], null, Cache.NoAbsoluteExpiration, new TimeSpan(10, 0, 0), CacheItemPriority.Normal, null); 
} 

var myitem = "test"; 
var myDict = HttpContext.Cache[myItem] as List<Car>; 

Würde die Implikation Leistung sehr unterschiedlich sein (da ich gehe davon aus, dass alles irgendwie in Erinnerung ist?)

+4

Denken Sie daran, dass Caches Mittel sind, um die Kosten für die Neuerstellung häufig verwendeter "teurer" Objekte zu sparen (dh die Kosten für die Neuerstellung übersteigen die Kosten für das Caching). Wenn es sich lohnt, zwischenzuspeichern, lassen Sie zu, dass der Cache LRU-Regeln anwendet, um die Leistung zu maximieren. Wenn Sie alle Einträge in einen einzigen Cache-Eintrag ('MyDictionary') setzen, wird die LRU besiegt und Sie riskieren, dass Sie die gesamte Menge verlieren, sollte der Cache entscheiden, dass MyDictionary weniger effizient ist als andere Einträge. – Will

Antwort

14

Hinzufügen einer zusätzlichen Antwort hier, da ich fühle, dass die vorhandene das "was", aber nicht genug des "warum" erfasst.

Der Grund, warum es am besten ist, einzelne Einträge separat im Cache zu speichern, hat wenig mit perf zu tun. Es hat vielmehr damit zu tun, dass das System eine angemessene Speicherverwaltung durchführen kann.

Es gibt eine Menge Logik im ASP.NET-Cache, um herauszufinden, was zu tun ist, wenn der Speicherdruck steigt. Am Ende muss es einige Gegenstände rausschmeißen, und das muss so wenig wie möglich geschehen. Welche Elemente es auswählt, hängt sehr davon ab, ob sie kürzlich aufgerufen wurden. Es gibt andere Faktoren, z. B. welche Flags zur Caching-Zeit übergeben werden. z.B. Sie können einen Gegenstand nicht entfernbar machen, und er wird nie rausgeschmissen.

Aber zurück zur Frage, wenn Sie Ihr gesamtes Wörterbuch als ein einzelnes Element speichern, lassen Sie nur zwei Optionen zum ASP.NET-Speichermanager: Behalte das Ganze am Leben, oder töte das Ganze. d. h., du verlierst den Vorteil, dass deine "heißen" Gegenstände im Cache bleiben, während deine selten zugänglichen Gegenstände, die den Speicher verschlingen, rausgeschmissen werden. Mit anderen Worten, Sie verlieren jede Ebene der Caching-Granularität.

Natürlich können Sie Ihr eigenes Schema in Ihrem Wörterbuch implementieren, um Elemente zu entfernen, die nur selten verwendet werden. Aber an diesem Punkt erfinden Sie das Rad neu, und Ihr neues Rad wird nicht so gut funktionieren, da es nicht mit dem Rest des Systems koordiniert wird.

3

Bei weitem der zweite Weg ist besser.

Denken Sie daran, viele Objekte berücksichtigen zu müssen. Jedes Mal, wenn Sie einen Wert erhalten müssen, müssen Sie ihn nur bekommen, anstatt das entyre Wörterbuch zu lesen und damit zu bekommen, was Sie wollen.

Dies, nicht über die Algorithmen im Cache verwendet, um die am häufigsten verwendeten Elemente (MRU, wenn ich mich noch erinnere) zu priorisieren.

Ich empfehle Ihnen nur die Leistungssteigerung zu messen, bevor Sie es als endgültige Implementierung übernehmen.

7

Wie Sie sagen, gibt es zwei entgegengesetzte Meinungen zu diesem Thema.

Worauf es wirklich ankommt, ist, dass Cache-Einträge wahrscheinlich auf der feinsten Ebene gespeichert werden sollten, wie sie benötigt werden. Damit meine ich, wenn Sie jeden Eintrag in Ihrem Wörterbuch jedes Mal verwenden, wenn es verwendet wird, dann speichern Sie es auf der Ebene der Wörterbücher.

Wenn Sie nur ein Element aus dem Wörterbuch verwenden und das Wörterbuch nicht durchgehen, speichern Sie es auf der individuellen Ebene.

Wenn Sie also die gesamte Sammlung als eine Einheit behandeln, dann speichern Sie sie als eine einzelne Einheit. Wenn auf die Sammlung zufällig zugegriffen wird und nur bestimmte Elemente gleichzeitig benötigt werden, speichern Sie sie auf der Ebene, auf der sie sich befindet.