JavaScript version of The TwoQueues cache model _ basic knowledge-js tutorial

Source: Internet
Author: User
This article describes how to implement the TwoQueues cache model in JavaScript. For more information, see the TwoQueues cache model described in this article.

Regardless of the language, some data may need to be stored in the memory to avoid repeated operations and reading. The most common scenario is the JQuery selector. The selection of some Dom elements is time-consuming. We hope to cache the data without having to re-traverse the Dom tree every call.

Save it, but there must be a volume! We can't always put all the historical data in the memory. After all, the current memory capacity is quite poor. Even if the memory is large enough, the memory allocated by each thread is theoretically limited.

So the question is, how can we efficiently cache truly useful data? This involves eliminating algorithms and eliminating junk data to save useful data.

There are several common ideas:

FIFO: a first-in-first-out queue, first-cached data, and first-out. This model is used inside the famous JQuery framework.

LRU: double-stranded table structure. New data is stored in the chain table and directly stored in the chain table header. The accessed data is also transferred to the chain table header, the data at the end of the linked list has not been used recently.

TwoQueues: FIFO + LRU. FIFO stores the data stored for the first time. LRU stores the hotspot data at least twice. This algorithm has a high hit rate, high adaptability, and low complexity.

There are many other elimination algorithms, but these two algorithms are actually used. Because their algorithms are not complex, easy to implement, and highly efficient to execute, the cache hit rate is acceptable in most cases. After all, the cache algorithm also consumes CPU resources. If it is too complicated, although the hit rate is improved, it is not worth the candle. Imagine how to cache data if it takes more time than getting data from the original location?

I will not talk much about the specific theory. I do not know much about it on the Internet. Today I will share with you the JavaScript version of The TwoQueues cache model.

Let's talk about the usage method first, which is very simple.

The basic usage is as follows:

[/Code]
Var tq = initTwoQueues (10 );
Tq. set ("key", "value ");
Tq. get ("key ");
[/Code]

During initialization, specify the cache capacity. Note that, because the internal implementation of FIFO + LRU is adopted, the actual capacity is twice the specified capacity. In the preceding example, 10 (key-value pairs) are specified ), in fact, 20 instances can be stored.

The capacity size needs to be determined based on the actual application scenario. If the capacity is too small, the hit rate is low, the capacity is too large, the efficiency is low, and the performance is extremely difficult. You need to estimate the capacity size by yourself.

During the development process, you can initialize the cache pool to the development version to review the cache effect:

The Code is as follows:


Var tq = initTwoQueues (10, true );
Tq. hitRatio ();

Simply add a parameter to the backend and set it to true. In this way, the initial cache pool will automatically calculate the hit rate. You can use the hitRatio method to obtain the hit rate. If this parameter is not added, the hit rate obtained by the hitRatio method is always 0.
The statistical hit rate must consume resources, so it is not recommended to enable it in the production environment.
It's time to share the Code:

The Code is as follows:


(Function (exports ){
/**
* The pure class used for inheritance
* @ Constructor
*/
Function Fn (){}
Fn. prototype = Elimination. prototype;
/**
* Parent class of the linked list-based Cache elimination algorithm
* @ Param maxLength cache capacity
* @ Constructor
*/
Function Elimination (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 = function (key ){
Throw new Error ("This method must be override! ");
};
Elimination. prototype. set = function (key, value ){
Throw new Error ("This method must be override! ");
};
/**
* Create a node in the linked list
* @ Param data refers to the data contained in the node, that is, the cached data value.
* @ Param key indicates the unique identifier of the node, that is, the cached key.
* @ Returns {{}}
*/
Elimination. prototype. buildNode = function (data, key ){
Var node = {};
Node. data = data;
Node. key = key;
Node. use = 0;
Return node;
};
/**
* A node pops up from the linked list header.
* @ 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;
Delete this. container [node. key];
This. length --;
}
Return node;
};
/**
* Insert a node from the linked list header.
* @ Param node object
* @ Returns {*}
*/
Elimination. prototype. unshift = function (node ){
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;
};
/**
* Insert a node from the end of the linked list
* @ Param node object
* @ Returns {*}
*/
Elimination. prototype. append = function (node ){
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;
};
/**
* A node pops up from the end of the linked list.
* @ 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;
Delete this. container [node. key];
This. length --;
}
Return node;
};
/**
* Remove a specified node from the linked list
* @ Param node object
* @ Returns {*}
*/
Elimination. prototype. remove = function (node ){
Node. prev. next = node. next;
Node. next. prev = node. prev;
Delete this. container [node. key];
This. length --;
Return node;
};
/**
* The processing required for a node to be accessed is to move the node to the head of the linked list.
* @ Param node
*/
Elimination. prototype. use = function (node ){
This. remove (node );
This. unshift (node );
};

/**
* LRU cache elimination algorithm implementation
* @ Constructor
*/
Function LRU (){
Elimination. apply (this, arguments );
}
LRU. prototype = new Fn ();
LRU. prototype. get = function (key ){
Var node = undefined;
Node = this. container [key];
If (node ){
This. use (node );
}
Return node;
};
LRU. prototype. set = function (key, value ){
Var node = this. buildNode (value, key );
If (this. length = this. maxLength ){
This. pop ();
}
This. unshift (node );
};

/**
* Implement the FIFO cache elimination algorithm
* @ Constructor
*/
Function FIFO (){
Elimination. apply (this, arguments );
}
FIFO. prototype = new Fn ();
FIFO. prototype. get = function (key ){
Var node = undefined;
Node = this. container [key];
Return node;
};
FIFO. prototype. set = function (key, value ){
Var node = this. buildNode (value, key );
If (this. length = this. maxLength ){
This. shift ();
}
This. append (node );
};

/**
* The LRU and FIFO algorithms are encapsulated to become the new twoqueues cache elimination algorithm.
* @ Param maxLength
* @ Constructor
*/
Function Agent (maxLength ){
This. getCount = 0;
This. hitCount = 0;
This. lir = new FIFO (maxLength );
This. hir = new LRU (maxLength );
}
Agent. prototype. get = function (key ){
Var node = undefined;
Node = this. lir. get (key );
If (node ){
Node. use ++;
If (node. use> = 2 ){
This. lir. remove (node );
This. hir. set (node. key, node. data );
}
} Else {
Node = this. hir. get (key );
}
Return node;
};
Agent. prototype. getx = function (key ){
Var node = undefined;
This. getCount ++;
Node = this. get (key );
If (node ){
This. hitCount ++;
}
Return node;
};
Agent. prototype. set = function (key, value ){
Var node = null;
Node = this. lir. container [key] | this. hir. container [key];
If (node ){
Node. data = value;
} Else {
This. lir. set (key, value );
}
};
/**
* Get hit rate
* @ Returns {*}
*/
Agent. prototype. hitRatio = function (){
Var ret = this. getCount;
If (ret ){
Ret = this. hitCount/this. getCount;
}
Return ret;
};
/**
* External interface
* @ Param maxLength cache capacity
* @ Param dev indicates whether the development environment is used. The Development Environment calculates the hit rate, but not vice versa.
* @ Returns {get, set: Function, hitRatio: Function }}
*/
Exports. initTwoQueues = function (maxLength, dev ){
Var api = new Agent (maxLength );
Return {
Get: (function (){
If (dev ){
Return function (key ){
Var ret = api. getx (key );
Return ret & ret. data;
};
} Else {
Return function (key ){
Var ret = api. get (key );
Return ret & ret. data;
};
}
}()),
Set: function (){
Api. set. apply (api, arguments );
},
HitRatio: function (){
Return api. hitRatio. apply (api, arguments );
}
};
};

} (This ));

Finally, I would like to remind you that the cache algorithm must be combined with the actual application scenario. If there is no universal algorithm, the best choice is the best!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.