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 ...
随机推荐
- BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...
- MySQL优化:如何避免回表查询?什么是索引覆盖? (转)
数据库表结构: create table user ( id int primary key, name varchar(20), sex varchar(5), index(name) )engin ...
- Windows下MongoDB的安装过程及基本配置
首先当然是到官网下载 MongoDB 了,点击进入后会看到下载页面,如下图所示: 安装有2种方式: 一种是通过直接点击下载的安装文件进行安装: 另一种是通过命令提示符来安装,下面我将直接通过第一种方式 ...
- ubantu 安装boost库 c++connector
安装libmysqlcppconn: sudo apt-get install libmysqlcppconn-dev 安装libboost: sudo apt-get install libboos ...
- linux安装python3 大型的软件一定要安装在/ opt中 规范
关闭页面特效 linux中安装python 1.首先切换目录 大型的软件一定要安装在/ opt中 规范 cd /opt 2.下载python3的源码 wget https://www.p ...
- RotateDrawable
用来对Drawable进行旋转,也是通过setLevel来控制旋转的,最大值也是:10000 相关属性如下: fromDegrees:起始的角度,,对应最低的level值,默认为0 toDegrees ...
- C#与C++数据类型比较及结构体转换(搜集整理二)
原文网址:http://www.blogjava.net/heting/archive/2010/03/20/315998.html C++ C# ========================== ...
- 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_04-vuejs研究-vuejs基础-v-model指令
<!DOCTYPE html> <html lang="en" xmlns:v‐on="http://www.w3.org/1999/xhtml&quo ...
- 下了个pkg包的jenkins,的使用方法
三.如何启动Jenkins1.最简单的方法是双击Jenkins的pkg包,一步一步点同意,默认8080端口2.使用命令行启动打开terminal,进入到war包所在目录,执行命令: java -jar ...
- Java8 根据对象某个属性值去重
list中的对象某个属性存在重复时将重复的对象去重 //根据skuAttrValueName值去重 List<SkuValue> uniqueSkuValues = skuValues.s ...