Das in diesem Artikel erwähnte Twoqueueues -Cache -Modell bezieht sich auf das Cache -Datenmodell im Speicher.
Unabhängig von der Sprache müssen Sie möglicherweise einige Daten in den Speicher setzen, um wiederholte Operationen und Lesen zu vermeiden. Das häufigste Szenario ist der JQuery -Selektor. Die Auswahl einiger DOM-Elemente ist sehr zeitaufwändig. Wir hoffen, diese Daten zu speichern, ohne den DOM-Baum jedes Mal neu zu übertrieben, wenn wir anrufen.
Speichern Sie es, aber es muss eine Menge geben! Sie können nicht alle historischen Daten in den Speicher bringen. Schließlich ist die aktuelle Speicherkapazität immer noch ziemlich erbärmlich. Auch wenn die Erinnerung groß genug ist, ist die in der Theorie theoretisch theoretisch zugewiesene Erinnerung immer noch begrenzt.
Die Frage ist also, wie können wir wirklich nützliche Daten effizient zwischenspeichern. Dies beinhaltet die Eliminierungsalgorithmen, und Junk -Daten müssen beseitigt werden, um nützliche Daten zu erhalten.
Es gibt mehrere gemeinsame Ideen:
FIFO: Es ist eine erste Warteschlange, die ersten zwischengespeicherten Daten, und wurde zuerst beseitigt. Dieses Modell wird im berühmten JQuery -Framework verwendet.
LRU: Die doppelt verknüpfte Listenstruktur, jedes Mal, wenn neue Daten gespeichert werden, wird sie direkt in der Kopfzeile der verknüpften Liste platziert. Die Daten, auf die jedes Mal zugegriffen wird, werden auch auf den Kopf der verknüpften Liste übertragen. Auf diese Weise sind die Daten am Ende der verlinkten Liste etwas, das in letzter Zeit nicht verwendet wurde und beseitigt wird.
Twoqueueues: FIFO+ LRU. FIFO speichert hauptsächlich zum ersten Mal gespeicherte Daten, und die LRU speichert Hotspot -Daten, die mindestens zweimal verwendet wurden. Dieser Algorithmus hat eine hohe Trefferquote, eine starke Anpassungsfähigkeit und eine geringe Komplexität.
Es gibt viele andere Eliminierungsalgorithmen, aber es gibt nur zwei Arten von ihnen, die in der Praxis mehr verwendet werden. Da ihre Algorithmen nicht komplex, einfach zu implementieren sind, ist eine hohe Ausführungseffizienz und der Cache -Treffer in den meisten Fällen akzeptabel. Der Cache -Algorithmus erfordert schließlich auch den CPU -Verbrauch. Wenn es zu komplex ist, obwohl die Trefferquote verbessert wurde, ist es den Verlust nicht wert. Stellen Sie sich vor, wenn Sie Daten aus dem Cache abrufen, dauert es mehr Zeit, als vom ursprünglichen Standort abzurufen. Wie nutzt Cache?
Ich werde nicht über die spezifischen Theorien sprechen. Es gibt einige online, aber ich verstehe sie nicht viel. Heute werde ich die JavaScript -Version des Twoqueueues -Cache -Modells mit Ihnen teilen.
Lassen Sie uns darüber sprechen, wie es zuerst verwendet werden kann, es ist sehr einfach.
Die grundlegende Verwendungsmethode lautet wie folgt:
[/Code]
var tq = intittwoqueueues (10);
tq.set ("Schlüssel", "Wert");
tq.get ("key");
[/Code]
Geben Sie beim Initialisieren einfach die Cache -Kapazität an. Es ist zu beachten, dass die tatsächliche Kapazität die tatsächliche Kapazität doppelt so hoch ist, dass FIFO+LRU intern implementiert wird. Das obige Beispiel gibt 10 (Schlüsselwertpaare) an, die tatsächlich 20 speichern können.
Die Kapazitätsgröße muss gemäß dem tatsächlichen Anwendungsszenario ermittelt werden. Wenn es zu klein ist, ist die Trefferquote niedrig, die Effizienz niedrig und das Extrem ist das Gegenteil, und Sie müssen sie selbst messen.
Während des Entwicklungsprozesses kann der Cache -Pool in die Entwicklungsversion initialisiert werden, um den Cache -Effekt zu überprüfen:
Die Codekopie lautet wie folgt:
var tq = inittwoqueues (10, true);
tq.hitratio ();
Fügen Sie einfach dem Ende einen Parameter hinzu und nur wahr. Der auf diese Weise initialisierte Cache -Pool zählt automatisch die Trefferquote und die Trefferquote kann durch die HitRatio -Methode erhalten werden. Wenn dieser Parameter nicht hinzugefügt wird, beträgt die von der Hitratio -Methode erhaltene Trefferquote immer 0.
Die statistische Trefferquote wird definitiv Ressourcen verbrauchen, sodass es nicht empfohlen wird, in Produktionsumgebungen einzuschalten.
Es ist Zeit, den Code zu teilen:
Die Codekopie lautet wie folgt:
(Funktion (exportiert) {
/**
* Reine Klasse für die Erbschaft
* @Constructor
*/
Funktion fn () {}
Fn.Prototype = elimination.prototype;
/**
* Übergeordnete Klasse von Cache -Eliminierungsalgorithmus basierend auf der verknüpften Liste
* @Param MaxLength Cache -Kapazität
* @Constructor
*/
Funktionsimination (maxLength) {
this.container = {};
this.length = 0;
this.maxLength = maxLength || 30;
this.linkhead = this.buildnode ("", "");
this.linkhead.head = true;
this.linkTail = this.buildnode ("", "");
this.linkTail.tail = true;
this.linkhead.next = this.linkTail;
this.linkTail.prev = this.linkhead;
}
Elimination.prototype.get = Funktion (Schlüssel) {
Neuen Fehler werfen ("Diese Methode muss überschrieben werden!");
};
Elimination.Prototype.set = Funktion (Schlüssel, Wert) {
Neuen Fehler werfen ("Diese Methode muss überschrieben werden!");
};
/**
* Erstellen Sie Knoten in der verlinkten Liste
* @Param -Daten Die im Knoten enthaltenen Daten, dh der zwischengespeicherte Datenwert
* @Paramschlüssel Die eindeutige Bezeichnung des Knotens, dh die zwischengespeicherte Taste
* @returns {{}}
*/
Elimination.prototype.buildnode = Funktion (Daten, Schlüssel) {
var node = {};
node.data = Daten;
node.key = key;
Knoten.use = 0;
Return Node;
};
/**
* Ein Knoten taucht aus dem Header der verknüpften Liste auf
* @returns {*}
*/
Elimination.prototype.shift = function () {
var node = null;
if (! this.linkhead.next.tail) {
node = this.linkhead.Next;
this.linkhead.next = node.next;
node.next.prev = this.linkhead;
löschen this.container [node.key];
diese.länge--;
}
Return Node;
};
/**
* Fügen Sie einen Knoten aus dem Header der verknüpften Liste ein
* @Param -Knotenknotenobjekt
* @returns {*}
*/
Elimination.prototype.unshift = Funktion (Knoten) {
node.next = this.linkhead.next;
this.linkhead.next.prev = node;
this.linkhead.next = node;
node.prev = this.linkhead;
this.container [node.key] = node;
this.length ++;
Return Node;
};
/**
* Fügen Sie einen Knoten vom Ende der verknüpften Liste ein
* @Param -Knotenknotenobjekt
* @returns {*}
*/
Elimination.Prototype.Append = Funktion (Knoten) {
this.linkTail.prev.Next = node;
node.prev = this.linkTail.prev;
node.next = this.linkTail;
this.linkTail.prev = node;
this.container [node.key] = node;
this.length ++;
Return Node;
};
/**
* Ein Knoten taucht vom Ende der verknüpften Liste auf
* @returns {*}
*/
Elimination.prototype.pop = function () {
var node = null;
if (! this.linkTail.prev.head) {
node = this.linkTail.prev;
node.prev.next = this.linkTail;
this.linkTail.prev = node.prev;
löschen this.container [node.key];
diese.länge--;
}
Return Node;
};
/**
* Entfernen Sie den angegebenen Knoten aus der verknüpften Liste
* @Param -Knotenknotenobjekt
* @returns {*}
*/
Elimination.prototype.remove = Funktion (Knoten) {
node.prev.next = node.next;
node.next.prev = node.prev;
löschen this.container [node.key];
diese.länge--;
Return Node;
};
/**
* Die Verarbeitung, die erforderlich ist, um auf einen Knoten zugegriffen zu werden
* @param node
*/
Elimination.prototype.use = Funktion (Knoten) {
this.remove (Knoten);
this.unshift (Knoten);
};
/**
* Implementierung des LRU -Cache -Eliminierungsalgorithmus
* @Constructor
*/
Funktion lRU () {
Elimination.Apply (dies, Argumente);
}
LRU.Prototype = new fn ();
LRU.Prototype.get = Funktion (Schlüssel) {
var node = undefiniert;
node = this.container [Schlüssel];
if (Knoten) {
diese. Use (Knoten);
}
Return Node;
};
LRU.Prototype.set = Funktion (Schlüssel, Wert) {
var node = this.buildnode (Wert, Schlüssel);
if (this.length === this.maxLength) {
this.pop ();
}
this.unshift (Knoten);
};
/**
* FIFO -Cache -Eliminierungsalgorithmus -Implementierung
* @Constructor
*/
Funktion FIFO () {
Elimination.Apply (dies, Argumente);
}
FIFO.Prototype = new fn ();
FIFO.Prototype.get = Funktion (Schlüssel) {
var node = undefiniert;
node = this.container [Schlüssel];
Return Node;
};
FIFO.Prototype.set = Funktion (Schlüssel, Wert) {
var node = this.buildnode (Wert, Schlüssel);
if (this.length === this.maxLength) {
this.shift ();
}
this.Append (Knoten);
};
/**
* LRU- und FIFO -Algorithmuskapselung ist zum neuen Twoqueueues -Cache -Eliminierungsalgorithmus geworden
* @param maxLength
* @Constructor
*/
Funktion Agent (maxLength) {
this.getCount = 0;
this.hitcount = 0;
this.lir = new fifo (maxLength);
this.hir = new LRU (maxLength);
}
Agent.Prototype.get = Funktion (Schlüssel) {
var node = undefiniert;
node = this.lir.get (Schlüssel);
if (Knoten) {
Knoten.use ++;
if (node.use> = 2) {
this.lir.remove (Knoten);
this.hir.set (node.key, node.data);
}
}anders{
node = this.hir.get (Schlüssel);
}
Return Node;
};
Agent.Prototype.getX = Funktion (Schlüssel) {
var node = undefiniert;
this.getCount ++;
node = this.get (Schlüssel);
if (Knoten) {
this.hitcount ++;
}
Return Node;
};
Agent.Prototype.set = Funktion (Schlüssel, Wert) {
var node = null;
node = this.lir.Container [Schlüssel] || this.hir.Container [Schlüssel];
if (Knoten) {
node.data = Wert;
}anders{
this.lir.set (Schlüssel, Wert);
}
};
/**
* Trefferquote erhalten
* @returns {*}
*/
Agent.Prototype.hitratio = function () {
var ret = this.getCount;
if (ret) {
ret = this.hitcount / this.getCount;
}
Rückkehr;
};
/**
* Externe Schnittstelle
* @Param MaxLength Cache -Kapazität
* @param dev, ob es sich um eine Entwicklungsumgebung handelt, die Entwicklungsumgebung wird die Trefferquote zählen, sonst nicht
* @returns {{get, set: function, hitRatio: function}}
*/
exports.inittwoqueues = function (maxLength, dev) {
var api = new Agent (maxLength);
zurückkehren {
get: (function () {
if (dev) {
Rückgabefunktion (Schlüssel) {
var ret = api.getX (Schlüssel);
ret Ret && ret.data;
};
}anders{
Rückgabefunktion (Schlüssel) {
var ret = api.get (Schlüssel);
ret Ret && ret.data;
};
}
} ()),
set: function () {
api.set.apply (API, Argumente);
},
hitRatio: function () {
api.hitratio.apply zurückgeben (API, Argumente);
}
};
};
}(Das));
Schließlich möchte ich Sie noch einmal daran erinnern, dass der Cache -Algorithmus mit tatsächlichen Anwendungsszenarien kombiniert werden muss. Ohne einen universellen Algorithmus ist das Beste am besten!