页面置换算法 - FIFO、LFU、LRU
缓存算法(页面置换算法)-FIFO. LFU. LRU
在前一篇文章中通过leetcode的一道题目了解了LRU算法的具体设计思路,下面继续来探讨一下另外两种常见的Cache算法:FIFO. LFU
1.FIFO算法
FIFO(First in First out),先进先出. 其实在操作系统的设计理念中很多地方都利用到了先进先出的思想,比如作业调度(先来先服务),为什么这个原则在很多地方都会用到呢?因为这个原则简单. 且符合人们的惯性思维,具备公平性,并且实现起来简单,直接使用数据结构中的队列即可实现.
在FIFO Cache设计中,核心原则就是:如果一个数据最先进入缓存中,则应该最早淘汰掉. 也就是说,当缓存满的时候,应当把最先进入缓存的数据给淘汰掉. 在FIFO Cache中应该支持以下操作;
get(key):如果Cache中存在该key,则返回对应的value值,否则,返回-1;
set(key,value):如果Cache中存在该key,则重置value值;如果不存在该key,则将该key插入到到Cache中,若Cache已满,则淘汰最早进入Cache的数据.
举个例子:假如Cache大小为3,访问数据序列为set(1,1),set(2,2),set(3,3),set(4,4),get(2),set(5,5)
则Cache中的数据变化为:
(1,1) set(1,1)
(1,1) (2,2) set(2,2)
(1,1) (2,2) (3,3) set(3,3)
(2,2) (3,3) (4,4) set(4,4)
(2,2) (3,3) (4,4) get(2)
(3,3) (4,4) (5,5) set(5,5)
那么利用什么数据结构来实现呢?
下面提供一种实现思路:
利用一个双向链表保存数据,当来了新的数据之后便添加到链表末尾,如果Cache存满数据,则把链表头部数据删除,然后把新的数据添加到链表末尾. 在访问数据的时候,如果在Cache中存在该数据的话,则返回对应的value值;否则返回-1. 如果想提高访问效率,可以利用hashmap来保存每个key在链表中对应的位置.
using namespace std;
// FIFO 先进先出原则
class Solution
{
public:
Solution(int si)
{
_size=si;
top_idx=0; // 队列top的下标
cache.clear();
exist.clear();
}
int check_page(int k)
{
if(exist.count(k)>=1) //hit the target
return k;
// not exist on cache
if(cache.size()<_size)
{
cache.push_back(k);
exist.insert(k);
}
else // replace
{
exist.erase(cache[top_idx]);
exist.insert(k);
cache[top_idx]=k;
++top_idx;
top_idx%=_size;
}
return -1;
}
private:
int _size,top_idx;
vector<int> cache;// 模拟队列
set<int> exist;
};
/**<
改进:
1.如果页面驻留集(cache)的大小很小的话,没必要使用set来判断是否存在于驻留集中,直接扫一遍来查找,节约了空间
*/
int main()
{
freopen("H:\\Code_Fantasy\\in.txt","r",stdin);
int n,page_number;
while(cin>>n)
{
int miss=0;
Solution solution(3); // set the cache size
for(int i=0;i<n;++i)
{
cin>>page_number;
if(solution.check_page(page_number)==-1)
++miss;
}
cout<<"Total missing page: "<<miss<<endl;
cout<<"The shooting rate is: "<<1.0-(1.*miss/n)<<endl;
cout<<"=====================================End."<<endl;
}
return 0;
}
/*
12
1 2 3 4 1 2 5 1 2 3 4 5
17
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1
*/
2.LFU算法
LFU(Least Frequently Used)最近最少使用算法. 它是基于“如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小”的思路.
注意LFU和LRU算法的不同之处,LRU的淘汰规则是基于访问时间,而LFU是基于访问次数的. 举个简单的例子:
假设缓存大小为3,数据访问序列为set(2,2),set(1,1),get(2),get(1),get(2),set(3,3),set(4,4),
则在set(4,4)时对于LFU算法应该淘汰(3,3),而LRU应该淘汰(1,1).
那么LFU Cache应该支持的操作为:
get(key):如果Cache中存在该key,则返回对应的value值,否则,返回-1;
set(key,value):如果Cache中存在该key,则重置value值;如果不存在该key,则将该key插入到到Cache中,若Cache已满,则淘汰最少访问的数据.
为了能够淘汰最少使用的数据,因此LFU算法最简单的一种设计思路就是:利用一个数组存储数据项,用hashmap存储每个数据项在数组中对应的位置,然后为每个数据项设计一个访问频次,当数据项被命中时,访问频次自增,在淘汰的时候淘汰访问频次最少的数据. 这样一来的话,在插入数据和访问数据的时候都能达到O(1)的时间复杂度,在淘汰数据的时候,通过选择算法得到应该淘汰的数据项在数组中的索引,并将该索引位置的内容替换为新来的数据内容即可,这样的话,淘汰数据的操作时间复杂度为O(n).
另外还有一种实现思路就是利用小顶堆+hashmap,小顶堆插入. 删除操作都能达到O(logn)时间复杂度,因此效率相比第一种实现方法更加高效.
如果哪位朋友有更高效的实现方式(比如O(1)时间复杂度),不妨探讨一下,不胜感激.
3.LRU算法
LRU算法的原理以及实现在前一篇博文中已经谈到,在此不进行赘述:
http://www.cnblogs.com/dolphin0520/p/3741519.html
参考链接:http://blog.csdn.net/hexinuaa/article/details/6630384
http://blog.csdn.net/beiyetengqing/article/details/7855933
http://blog.csdn.net/alexander_xfl/article/details/12993565
http://outofmemory.cn/wr/?u=http%3A%2F%2Fblog.csdn.net%2Fyunhua_lee%2Farticle%2Fdetails%2F7648549
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
* Author: crazyacking
* Date : 2016-03-15-20.01
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long(LL);
typedef unsigned long long(ULL);
const double eps(1e-8);
struct Node
{
int key,value;
Node(int k,int v):key(k),value(v){}
};
class LRUCache
{
private:
int max_size;
list<Node> cacheList;
unordered_map<int,list<Node>::iterator> mp;
public:
LRUCache(int capacity) {max_size=capacity;}
int get(int key)
{
if(mp.find(key)==mp.end()) // 未命中
return -1;
else
{
auto list_it=mp[key];
Node node(key,list_it->value);
cacheList.erase(list_it);
cacheList.push_front(node);
mp[key]=cacheList.begin();
return node.value;
}
}
void set(int key, int value)
{
auto it=mp.find(key);
if(it==mp.end()) // 未命中
{
if(cacheList.size()>=max_size) // 驻留集已满
{
mp.erase(cacheList.back().key);
cacheList.pop_back();
}
Node node(key,value);
cacheList.push_front(node);
mp[key]=cacheList.begin();
}
else // 命中,将加入的结点置于链表头部,表示最近一次使用
{
cacheList.erase(mp[key]);
Node node(key,value);
cacheList.push_front(node);
mp[key]=cacheList.begin();
}
}
};
int main()
{
LRUCache cache(3);
cache.set(1,1);
cache.set(2,2);
cache.set(3,3);
cache.set(4,4);
cout<<cache.get(4)<<endl;
cout<<cache.get(3)<<endl;
cout<<cache.get(2)<<endl;
cout<<cache.get(1)<<endl;
cache.set(5,5);
cout<<cache.get(1)<<endl;
cout<<cache.get(2)<<endl;
cout<<cache.get(3)<<endl;
cout<<cache.get(4)<<endl;
cout<<cache.get(5)<<endl;
return 0;
}
/*
*/
--------------------------------------------------------- End.
转载请注明:http://www.cnblogs.com/crazyacking/
页面置换算法 - FIFO、LFU、LRU相关推荐
- Cache与页面置换算法FIFO、LRU等
1 Cache与存储结构 (1) 定义 狭义的Cache指的是位于CPU和主存间的快速RAM, 通常它不像系统主存那样使用动态随机存取存储器(Dynamic Random Access Memory, ...
- 操作系统 页面置换算法FIFO与LRU的实现
FIFO FIFO算法是最早出现的置换算法.该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰. LRU 最近最久未使用(LRU)的页面置换算法是根据页面调入内存后的使用情况做 ...
- 页面置换算法 FIFO和LRU 及各自的命中率
(1) 先进先出算法FIFO:该算法的实质是选择作业中在主存驻留时间最长的一页淘汰,这种算法容易实现,例如分配一个作业的存储块数为m,则只需建立一张m个元素的队列表Q(0).Q(1).-.Q(m-1) ...
- 操作系统实验--存储管理--页面置换算法--FIFO and LRU c++实现
#include<iostream> #include <stdio.h> #include <stdlib.h> #include <time.h> ...
- 最近最久未使用页面置换算法C语言,LRU页面置换算法模拟-最近最久未使用置换算法...
LRU页面置换算法模拟-最近最久未使用置换算法 LRU页面置换算法模拟-最近最久未使用置换算法|课程设计|计算机数据库课程设计 一.设计目的 1.用C语言实现最近最久未使用(LRU)置换算法. 2.了 ...
- 请求分页系统中的置换算法(FIFO、LRU、Optimal)
操作系统实验导航 实验一:银行家算法 https://blog.csdn.net/weixin_46291251/article/details/115384510 实验二:多级队列调度和多级反馈队列 ...
- 7-1 页面置换算法--FIFO (50 分)(思路详解)
一:题目 先初始化页面大小,和物理块数.连续输入页面的逻辑地址,以"-1"作为结束标志,采用FIFO页面置换算法.固定分配局部置换分配策略.输出该页面的页号和页内位移,若该页不在内 ...
- OS 页面置换算法(OPT,FIFO,LRU)颠簸/抖动
介绍 置换算法 置换算法(replacement algorithm)又称为淘汰算法.替换算法,用于确定页面的调出原则. 在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断.当发 ...
- 页面置换算法(FIFO、第二次机会、LRU)
页面置换算法 文章目录 页面置换算法 前言 一.最近未使用页面置换算法 二.先进先出页面置换算法 三.第二次机会页面置换算法 四.时钟页面置换算法 四.最近最少使用页面置换算法 四.最不常用算法 总结 ...
最新文章
- Android博客文章整理
- 如何花钱让2000元的月收入工资价值最大化?
- 如何求两个向交矩形的交集的面积?
- drop table中cascade的含义及用法
- Kafka Producer拦截器
- mysql update修改数据_MySQL UPDATE:修改数据(更新数据)
- 压缩和解压文件:tar gzip bzip2 compress(转)
- php ascii art,ASCII art (简体中文)
- linux rsync 目录同步,Linux rsync网站目录同步功能的实现
- 解决微信小程序Video 某些属性设置不起作用问题
- 四张照片合成一张怎么弄_教你5种照片创意手工,简单好看实用
- 加盟店 -- 祖坟刨干记
- Java常用API——学习笔记(7)
- python总结(数据类型、逻辑控制、函数、类与对象、推导式、解包、类型转换、异常、上下文、jsonpath、定时器)
- 爬楼梯当中的递归简化计算
- python 可执行文件大_python – 如何使用pyinstaller创建最小大小的可执行文件?
- Java web:基于jieba分词器(或ansj分词器)的文章关键词字符云(词云图)
- 基于keepalived的mysql_【实用】基于keepalived的mysql双主高可用系统
- ALNS求MDHVRPTW问题 python实现
- CH340有线USB转串与CH9140无线蓝牙转串