LRU算法简介
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算法简介的更多相关文章
- Java实现LRU算法
一.LRU算法简介 LRU(Least Recently Used)最近最久未使用算法 常见应用场景:内存管理中的页面置换算法.缓存淘汰中的淘汰策略等 二.实现理论 底层结构:双向链表 + HashM ...
- mysql 原理 ~ LRU 算法与buffer_pool
一 简介:针对查询和事务的页在内存中的处理,是如何进行的 二 LRU算法 普通 : 实现的是末尾淘汰法,当整个链表已满时,淘汰尾部,将新的数据页加入头部 mysql_lru改进 : 分为两部分 yan ...
- Guava---缓存之LRU算法
随笔 - 169 文章 - 0 评论 - 292 GuavaCache学习笔记一:自定义LRU算法的缓存实现 前言 今天在看GuavaCache缓存相关的源码,这里想到先自己手动实现一个LRU ...
- LRU算法介绍和在JAVA的实现及源码分析
一.写随笔的原因:最近准备去朋友公司面试,他说让我看一下LRU算法,就此整理一下,方便以后的复习. 二.具体的内容: 1.简介: LRU是Least Recently Used的缩写,即最近最少使用. ...
- Android图片缓存之Lru算法
前言: 上篇我们总结了Bitmap的处理,同时对比了各种处理的效率以及对内存占用大小.我们得知一个应用如果使用大量图片就会导致OOM(out of memory),那该如何处理才能近可能的降低oom发 ...
- 缓存淘汰算法--LRU算法
1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也 ...
- 借助LinkedHashMap实现基于LRU算法缓存
一.LRU算法介绍 LRU(Least Recently Used)最近最少使用算法,是用在操作系统中的页面置换算法,因为内存空间是有限的,不可能把所有东西都放进来,所以就必须要有所取舍,我们应该把什 ...
- LinkedHashMap实现LRU算法
LinkedHashMap特别有意思,它不仅仅是在HashMap上增加Entry的双向链接,它更能借助此特性实现保证Iterator迭代按照插入顺序(以insert模式创建LinkedHashMap) ...
- LinkedHashMap 和 LRU算法实现
个人觉得LinkedHashMap 存在的意义就是为了实现 LRU 算法. public class LinkedHashMap<K,V> extends HashMap<K,V&g ...
随机推荐
- 元祖(tuple)
元祖和列表几乎是一样的: 列表是可以进行修改的,它可以填加一个元素,也可以移除一个元素,但元祖是不能修改的 如果我们以后想导一个集合,这个集合以后不允许修改,我们用元祖:如何我们想让别人进行修改,我们 ...
- Feeding Chicken
D - Feeding Chicken 从左上角开始,往右下角开始遍历,但是遍历的时候需要注意一点,就是遍历的时候需要连起来,就比如第一行从左往右进行遍历,但是第二行不能从左往右了,因为这样就分开了, ...
- Docker安装mysql5.6
1.docker hub 上查找mysql镜像 2.在docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.6 3.使用mysql5.6创建容器(也叫运行镜像) 4.交互运行,进入m ...
- 你的windows许可证即将过期
0xC004F025拒绝访问:所请求的操作需要提升特权:解决方法:1.打开我的电脑找到windows System32目录下的cmd 2.对windows System ...
- GA算法及参数对结果的影响
1.遗传算法简介 遗传算法是一种基于自然选择和群体遗传机理的搜索算法,它模拟了自然选择和自然遗传过程中的繁殖.杂交和突变现象.再利用遗传算法求解问题时,问题的每一个可能解都被编码成一个“染色体”,即个 ...
- windows下安装node.js及环境配置、部署项目
windows下安装node.js及环境配置.部署项目 一.总结 一句话总结: 安装nodejs软件:就像普普通通的的软件那样安装 配置nodejs安装的全局模块的环境变量 并且安装cnpm(比如cn ...
- [go]template使用
//index.html {{if gt .Age 18}} <p>hello, old man, {{.Name}}</p> {{else}} <p>hello, ...
- SQL-W3School-高级:SQL 数据类型
ylbtech-SQL-W3School-高级:SQL 数据类型 1.返回顶部 1. Microsoft Access.MySQL 以及 SQL Server 所使用的数据类型和范围. Microso ...
- yum -y与 yum有什么区别
在linux中,经常使用yum来进行软件的安装,更新与卸载,那我们会发现,在使用yum的时候,通常有下面两种指令模式: ①yum install xxx ②yum -y install xx 那这 ...
- 09 Flutter底部Tab切换保持页面状态的几种方法
IndexedStack:保此所有页面的状态: AutomaticKeepAliveClientMixin:保此部分页面的状态: 修改的页面代码: 页面效果: Tabs.dart import 'pa ...