LRU是什么?

按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非常注明的计算机操作系统基础理论得来的:最近使用的页面数据会在未来一段时期内仍然被使用,已经很久没有使用的页面很有可能在未来较长的一段时间内仍然不会被使用。基于这个思想,会存在一种缓存淘汰机制,每次从内存中找到最久未使用的数据然后置换出来,从而存入新的数据!它的主要衡量指标是使用的时间,附加指标是使用的次数。在计算机中大量使用了这个机制,它的合理性在于优先筛选热点数据,所谓热点数据,就是最近最多使用的数据!因为,利用LRU我们可以解决很多实际开发中的问题,并且很符合业务场景。

1.2:小王的困惑

当小王看到LRU的时候,瞬间感觉抓住了救命稻草,这个算法不是就完全契合产品的需求吗?只要把用户数据按照LRU去筛选,利用数据结构完成的事情,完全减少了自己存储、添加字段判断、排序的过程,这样对于提高服务器性能肯定有很大的帮助,岂不美哉!小王考虑好之后,就决定先写一个demo来实现LRU,那么在php中是如何实现LRU呢?考虑了许久。以上内容来自互联网 直接 上代码

 <?php
require_once('PHPUnit/Autoload.php');
require_once(dirname(__FILE__).'/../src/LRUCache/LRUCache.php'); class LRUCacheTest extends PHPUnit_Framework_TestCase { public function testStartsEmpty() {
$lru = new \LRUCache\LRUCache(1000);
$this->assertNull($lru->get(1));
} public function testGet() {
$lru = new \LRUCache\LRUCache(1000);
$key = 'key1';
$data = 'content for key1';
$lru->put($key, $data);
$this->assertEquals($lru->get($key), $data);
} public function testMultipleGet() {
$lru = new \LRUCache\LRUCache(1000);
$key = 'key1';
$data = 'content for key1';
$key2 = 'key2';
$data2 = 'content for key2'; $lru->put($key, $data);
$lru->put($key2, $data2); $this->assertEquals($lru->get($key), $data);
$this->assertEquals($lru->get($key2), $data2);
} public function testPut() {
$numEntries = 1000;
$lru = new \LRUCache\LRUCache($numEntries); $key1 = 'mykey1';
$value1 = 'myvaluefromkey1'; $lru->put($key1, $value1);
$this->assertEquals($lru->get($key1), $value1);
} public function testMassivePut() {
$numEntries = 90000;
$lru = new \LRUCache\LRUCache($numEntries); while($numEntries > 0) {
$lru->put($numEntries - 899999, 'some value...');
$numEntries--;
}
} public function testRemove() {
$numEntries = 3;
$lru = new \LRUCache\LRUCache($numEntries); $lru->put('key1', 'value1');
$lru->put('key2', 'value2');
$lru->put('key3', 'value3'); $ret = $lru->remove('key2');
$this->assertTrue($ret); $this->assertNull($lru->get('key2')); // test remove of already removed key
$ret = $lru->remove('key2');
$this->assertFalse($ret); // make sure no side effects took place
$this->assertEquals($lru->get('key1'), 'value1');
$this->assertEquals($lru->get('key3'), 'value3');
} public function testPutWhenFull() {
$lru = new \LRUCache\LRUCache(3); $key1 = 'key1';
$value1 = 'value1forkey1';
$key2 = 'key2';
$value2 = 'value2forkey2';
$key3 = 'key3';
$value3 = 'value3forkey3';
$key4 = 'key4';
$value4 = 'value4forkey4'; // fill the cache
$lru->put($key1, $value1);
$lru->put($key2, $value2);
$lru->put($key3, $value3); // access some elements more often
$lru->get($key2);
$lru->get($key2);
$lru->get($key3); // put a new entry to force cache to discard the oldest
$lru->put($key4, $value4); $this->assertNull($lru->get($key1));
}
}
 <?php

 namespace LRUCache;

 /**
* Class that implements the concept of an LRU Cache
* using an associative array as a naive hashmap, and a doubly linked list
* to control the access and insertion order.
*
* @author Rogério Vicente
* @license MIT (see the LICENSE file for details)
*/
class LRUCache { // object Node representing the head of the list
private $head; // object Node representing the tail of the list
private $tail; // int the max number of elements the cache supports
private $capacity; // Array representing a naive hashmap (TODO needs to pass the key through a hash function)
private $hashmap; /**
* @param int $capacity the max number of elements the cache allows
*/
public function __construct($capacity) {
$this->capacity = $capacity;
$this->hashmap = array();
$this->head = new Node(null, null);
$this->tail = new Node(null, null); $this->head->setNext($this->tail);
$this->tail->setPrevious($this->head);
} /**
* Get an element with the given key
* @param string $key the key of the element to be retrieved
* @return mixed the content of the element to be retrieved
*/
public function get($key) { if (!isset($this->hashmap[$key])) { return null; } $node = $this->hashmap[$key];
if (count($this->hashmap) == 1) { return $node->getData(); } // refresh the access
$this->detach($node);
$this->attach($this->head, $node); return $node->getData();
} /**
* Inserts a new element into the cache
* @param string $key the key of the new element
* @param string $data the content of the new element
* @return boolean true on success, false if cache has zero capacity
*/
public function put($key, $data) {
if ($this->capacity <= 0) { return false; }
if (isset($this->hashmap[$key]) && !empty($this->hashmap[$key])) {
$node = $this->hashmap[$key];
// update data
$this->detach($node);
$this->attach($this->head, $node);
$node->setData($data);
}
else {
$node = new Node($key, $data);
$this->hashmap[$key] = $node;
$this->attach($this->head, $node); // check if cache is full
if (count($this->hashmap) > $this->capacity) {
// we're full, remove the tail
$nodeToRemove = $this->tail->getPrevious();
$this->detach($nodeToRemove);
unset($this->hashmap[$nodeToRemove->getKey()]);
}
}
return true;
} /**
* Removes a key from the cache
* @param string $key key to remove
* @return bool true if removed, false if not found
*/
public function remove($key) {
if (!isset($this->hashmap[$key])) { return false; }
$nodeToRemove = $this->hashmap[$key];
$this->detach($nodeToRemove);
unset($this->hashmap[$nodeToRemove->getKey()]);
return true;
} /**
* Adds a node to the head of the list
* @param Node $head the node object that represents the head of the list
* @param Node $node the node to move to the head of the list
*/
private function attach($head, $node) {
$node->setPrevious($head);
$node->setNext($head->getNext());
$node->getNext()->setPrevious($node);
$node->getPrevious()->setNext($node);
} /**
* Removes a node from the list
* @param Node $node the node to remove from the list
*/
private function detach($node) {
$node->getPrevious()->setNext($node->getNext());
$node->getNext()->setPrevious($node->getPrevious());
} } /**
* Class that represents a node in a doubly linked list
*/
class Node { /**
* the key of the node, this might seem reduntant,
* but without this duplication, we don't have a fast way
* to retrieve the key of a node when we wan't to remove it
* from the hashmap.
*/
private $key; // the content of the node
private $data; // the next node
private $next; // the previous node
private $previous; /**
* @param string $key the key of the node
* @param string $data the content of the node
*/
public function __construct($key, $data) {
$this->key = $key;
$this->data = $data;
} /**
* Sets a new value for the node data
* @param string the new content of the node
*/
public function setData($data) {
$this->data = $data;
} /**
* Sets a node as the next node
* @param Node $next the next node
*/
public function setNext($next) {
$this->next = $next;
} /**
* Sets a node as the previous node
* @param Node $previous the previous node
*/
public function setPrevious($previous) {
$this->previous = $previous;
} /**
* Returns the node key
* @return string the key of the node
*/
public function getKey() {
return $this->key;
} /**
* Returns the node data
* @return mixed the content of the node
*/
public function getData() {
return $this->data;
} /**
* Returns the next node
* @return Node the next node of the node
*/
public function getNext() {
return $this->next;
} /**
* Returns the previous node
* @return Node the previous node of the node
*/
public function getPrevious() {
return $this->previous;
} }

以上代码仅供大家参考

LRU算法简介的更多相关文章

  1. Java实现LRU算法

    一.LRU算法简介 LRU(Least Recently Used)最近最久未使用算法 常见应用场景:内存管理中的页面置换算法.缓存淘汰中的淘汰策略等 二.实现理论 底层结构:双向链表 + HashM ...

  2. mysql 原理 ~ LRU 算法与buffer_pool

    一 简介:针对查询和事务的页在内存中的处理,是如何进行的 二 LRU算法 普通 : 实现的是末尾淘汰法,当整个链表已满时,淘汰尾部,将新的数据页加入头部 mysql_lru改进 : 分为两部分 yan ...

  3. Guava---缓存之LRU算法

    随笔 - 169  文章 - 0  评论 - 292 GuavaCache学习笔记一:自定义LRU算法的缓存实现   前言 今天在看GuavaCache缓存相关的源码,这里想到先自己手动实现一个LRU ...

  4. LRU算法介绍和在JAVA的实现及源码分析

    一.写随笔的原因:最近准备去朋友公司面试,他说让我看一下LRU算法,就此整理一下,方便以后的复习. 二.具体的内容: 1.简介: LRU是Least Recently Used的缩写,即最近最少使用. ...

  5. Android图片缓存之Lru算法

    前言: 上篇我们总结了Bitmap的处理,同时对比了各种处理的效率以及对内存占用大小.我们得知一个应用如果使用大量图片就会导致OOM(out of memory),那该如何处理才能近可能的降低oom发 ...

  6. 缓存淘汰算法--LRU算法

    1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也 ...

  7. 借助LinkedHashMap实现基于LRU算法缓存

    一.LRU算法介绍 LRU(Least Recently Used)最近最少使用算法,是用在操作系统中的页面置换算法,因为内存空间是有限的,不可能把所有东西都放进来,所以就必须要有所取舍,我们应该把什 ...

  8. LinkedHashMap实现LRU算法

    LinkedHashMap特别有意思,它不仅仅是在HashMap上增加Entry的双向链接,它更能借助此特性实现保证Iterator迭代按照插入顺序(以insert模式创建LinkedHashMap) ...

  9. LinkedHashMap 和 LRU算法实现

    个人觉得LinkedHashMap 存在的意义就是为了实现 LRU 算法. public class LinkedHashMap<K,V> extends HashMap<K,V&g ...

随机推荐

  1. git修改下载地址

    git查看远程地址git remote -v修改git remote set-url origin [url]

  2. League of Leesins

    C - League of Leesins 首先找到每一串数字的头和尾两个数字,这两个数字有一个特点,就是它们在输入数据的时候都只会出现一次.我们在输出的时候用头和尾做第一数都可以. 然后第二个数只会 ...

  3. UVALive 5052 Genome Evolution ——(xjbg)

    本以为这题n=3000,随便n方一下就能过.于是我先枚举长度len再枚举起点,不断增加新的点并删除原来的点,判断在b中的r-l+1是不是等于len即可,这个过程显然要用set维护比较方便,但是貌似卡了 ...

  4. ZR#996

    ZR#996 解法: 若删除长度为 $ x $ 的子串后序列中没有相同元素,那么一定有至少一个长度为 $ x+1 $ 的子串,删除它后序列中也没有相同元素. CODE: #include <io ...

  5. Js 之将字符串当变量使用

    var page1 = 0; var p = "page1"; //修改值 window[p] += 1; var value = eval(p);

  6. Mybatis 传入多个参数查询数据 (3种方法)

    第一种方案 DAO层的函数方法 public User selectUser(String name,String area); 对应的Mapper.xml <select id="s ...

  7. 浅述不同版本ios系统有什么特点 ios 1 -ios 12

    版本记录 版本号 时间 V2.0 2019.08.20 前言 到目前为止,ios的版本已经发到了ios11的测试版,今年正式版马上就会出来,ios发布了这么多的版本,到底每个版本都有什么显著的特点?用 ...

  8. Colab 实用教程

    Google Colab 是什么? Google Colab 是一个免费的云服务,现在它还支持免费的 GPU! 你可以: 提高你的 Python 语言的编码技能. 使用 Keras.TensorFlo ...

  9. Memcached与Memcache区别

    在写这篇文章之前一直对memcache .memcached模糊,相差一个字母,特此总结下: Memcache是什么? Memcache是一个自由和开放源代码.高性能.分配的内存对象缓存系统.用于加速 ...

  10. 在使用vagrant访问PHP文件是报错“file not found”,好像是最新的NGINX不能识别document_root,只能改为自己的项目目录/vagrant_data

    出现该错误有很多可能,有可能是root配置不对,有可能是fastcgi_param SCRIPT_FILENAME参数不对等. 而本人遇到的也是参数不对,但是是一个比较少人提及的问题,nginx版本不 ...