OPT,FIFO,LRU页面置换算法的JS实现
一.FIFO算法
1.1 先进先出算法基本思想:
淘汰最先进入的页面,选择在内存中驻留最久的页面的予以淘汰。
基本思想就是将先进入队列的页面先淘汰掉,如果该页面后期被命中,那也不将它的步数重置,而是按照它第一次进入页面开始记步数
二. LRU算法
2.1 LRU置换算法基本思想:
Lru算法和fifo最大相似点就是淘汰前向步数最大的页面,也就是淘汰页面的判断依据是该页面的从前到后的步数统计,越大表明越是长时间为用到,所以予以淘汰替换。
单很明显是由明显区别的,那就是lru算法当遇到命中时会将该页面重置步数。
三.Optimal算法:
3.1 最佳置换算法基本思想:
将以后永不使用的淘汰,或者是将在最长(未来)时间内不在访问的页面淘汰。由于不能知道或预测谁是最可能永不使用或者长时间使用的页面,所以不能拿它来作为页面置换实际操作中的算法,但是可以用于评估其他算法。
(未被命中的即为“缺页”,缺页率=未命中数/总数,淘汰率=替换数/总数)
3.2具体操作思想
首先有一个页面访问顺序的数列2,3,1,5,6,7,6,3,7,8,2。内存块有3个物理块
四.运行截图
五.代码:
<!DOCTYPE html>
<html>
<head>
<title>页面替换算法OPT,FIFO,LRU</title>
<meta charset="utf-8">
<meta author="syk">
</head>
<link rel="stylesheet" href="reset.css">
<style>
.container{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: #00ace6;
}
.container-warrper{
width: 700px;
padding: 0 0 0 0;
margin: 100px auto;
border: 1px dashed #cccccc;
}
.container span{
color: #ffffff;
}
#liststyle{
width: 600px;
background: #ffffff;
margin-top: 10px;
}
#substyle{
text-align: center;
}
#part{
margin: 20px 0 20px 0;
color: #ffffff;
text-align: center;
height: 25px;
line-height: 25px;
}
.arithmetic{
}
#but1 ,#but2 ,#but3{
border-radius: 50%;
background-color: bisque;
outline: none;
color: #000000;
font-weight: 700;
}
#result1 ,#result2 ,#result3{
color: #ffffff;
font-weight: 600;
text-align: center;
}
</style>
<body>
<div class="container">
<div class="container-warrper">
<form action="#" method="POST">
<span>页面序列:</span> <input type="text" name="list" id="liststyle" value="" placeholder="请按照'1 2 3 4 . . .'带有空格的方式写 输入7个数吧!!"> <br/>
<input type="submit" value="确认" id="substyle">
<p style="color:#ffffff;">-----------------------------------------------------------------------------------------------------</p>
<p id="part"></p>
</form>
<div class="arithmetic">
<p style="color:#ffffff;">-----------------------------------------------------------------------------------------------------</p>
<button id="but1">OPT算法</button>
<button id="but2">FIFO算法</button>
<button id="but3">LRU算法</button>
<p style="color:#ffffff;">-----------------------------------------------------------------------------------------------------</p>
<div id="result1"></div>
<p style="color:#ffffff;">-----------------------------------------------------------------------------------------------------</p>
<div id="result2"></div>
<p style="color:#ffffff;">-----------------------------------------------------------------------------------------------------</p>
<div id="result3"></div>
</div>
</div>
</div>
</body>
<script type="text/javascript">
var Button=document.getElementById('substyle');
var Logic1=document.getElementById('but1');//opt算法对象
var Logic2=document.getElementById('but2');//fifo算法对象
var Logic3=document.getElementById('but3');//lru算法对象
var textlist=document.getElementById('liststyle');
var list =new Array();
var Plist= new Array();//页面序列
var M=new Array();
// M=[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]];//物理存储块向量7
var target=0;
var pointPage=0;//命中数
//实现的是点击获取当前的form表单输入值,置换成数组形式Plist[];
Button.onclick=function(){
var x=textlist.value;
list=x.split(" ");
list.forEach(element => {
Plist.push(parseInt(element));
});
console.log(Plist);
document.getElementById('part').innerHTML="当前的页面调入数组是:["+ Plist +"]";
console.log(target);
return false;
}
// var a=1;
// document.getElementById('result1').innerHTML='‘'+a+'’';
// a++;
// document.getElementById('result2').innerHTML='‘'+a+'’';
var headlist=new Array();//上一次的数组
var B=new Array();
var C=new Array();
// C=[0,0,0];
function init(){
M=[[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]];
C=[0,0,0];
pointPage=0;
}
Logic1.onclick=()=>{
console.log("OPT");
// MisPage=3;
init();
Plist.forEach((p,i) => {
if(i<=2){ //前三个是一定要产生缺页的,所以直接插入
var w=i;
for(w;w>=0;w--){
if(w!=i){
M[i].splice(w,1,B[w]); //当没到和当前p匹配的位置时,前面都是引用上一个的数组的值。
}else{
M[i].splice(w,1,p);
}
} //复杂度是一个m*n的空间复杂度。
B=M[i];
console.log("M["+M[i]+"]");
// M[i+1]=B;//数组是引用类型,这里会将地址统一到m[0]处,这样后面的变了,前面的理所当然的变了,所以说这里不是用引用类型!!!。
// debugger;
}else{//进入的条件就是数组遍历到了第i=3的位置,这时如果数组是[1,2,3,4,5,1,2],那么就会是4准备入页面了,
if(M[i-1].some((value)=>{return value==p;})){//命中了!!这里应该用前一个索引作为当前基准,也就是说不应该是i,应为i是外面的,一直没变。。。
M[i-1].forEach((element,indx) => {
M[i].splice(indx,1,element);
});
pointPage++;
}else{//没有命中则要发生替换算法了!!,
for(let [index, item] of Plist.entries()){
if(index>i-1){//从第4条开始寻找。以后依次往后寻找
M[i-1].forEach((element,i) => {
if(element==item){
if(C[i]!=0&&C[i]<index){
//找最近被替换的索引,怕出现1这个数后面出现两次,结果将大的索引去替换了之前小的索引。
}else{
C[i]=index;//当前所需知道的物理存储块的后面所最近出现的位置,位置越大越表示要被替换
}
}
});
}//最终找到了我们的其前面对应的3个页面各自在后方的最近被访问的索引,下面只需要比较谁大了,越大证明越远被访问到,所以被替换
}//计算当前被替换的3个物理块中个元素在后面最先调入的索引,也就是我们所说的后面的距离。
var x=C.indexOf(C.reduce((a,b)=>{return a>b?a:b;}));//得到应该被替换的数组的索引。
// debugger;
M[i-1].forEach((element,indx) => {
M[i].splice(indx,1,element);
});
M[i].splice(x,1,p);
// MisPage++;
}
// }
// }
}
});
// dom操作,添加输出的信息。
M.forEach((element,index) => {
// debugger;
M[index].forEach((e,i)=>{
console.log(e);
document.getElementById('result1').innerHTML="<p>["+M+"]</p><br/><p>缺页率:"+(Plist.length-pointPage)/Plist.length+"</p>";//这里用innerHTML最后会被覆盖
})
});
}
Logic2.onclick=()=>{//比较的是我们的,主流时间最长的淘汰
init();
C=[M[0].length,M[0].length-1,M[0].length-2];
console.log("FIFO");
Plist.forEach((p,i) => {
// debugger;
if(i<=2){ //前三个是一定要产生缺页的,所以直接插入
var w=i;
var stp;
for(w;w>=0;w--){
if(w!=i){
M[i].splice(w,1,B[w]); //当没到和当前p匹配的位置时,前面都是引用上一个的数组的值。
}else{
M[i].splice(w,1,p);
}
} //复杂度是一个m*n的空间复杂度。
B=M[i];
console.log("M["+M[i]+"]");
// M[i+1]=B;//数组是引用类型,这里会将地址统一到m[0]处,这样后面的变了,前面的理所当然的变了,所以说这里不是用引用类型!!!。
// debugger;
}else{//开始判断C,和改变C。//声明一下,如果被命中了,则改处的C的计数从1开始
if(M[i-1].some((value)=>{return value==p;})){//命中了!!这里应该用前一个索引作为当前基准,也就是说不应该是i,应为i是外面的,一直没变。。。
M[i-1].forEach((element,indx) => {
M[i].splice(indx,1,element);
});
C.forEach((e,idx)=>{
C.splice(idx,1,e+1);
})//命中每一个前面等待的加1。
pointPage++;
}else{//没命中的话怎么办呢?比较C数组,决定替换最大的那个,
var x=C.indexOf(C.reduce((a,b)=>{return a>b?a:b;}));//找到最先来的是谁。
// debugger;
M[i-1].forEach((element,indx) => {
M[i].splice(indx,1,element);
});
M[i].splice(x,1,p);
C.forEach((e,idx)=>{
C.splice(idx,1,e+1);
});
C.splice(x,1,1);//与此同时被替换的位置则重置为1。
}
}
});
M.forEach((element,index) => {
// debugger;
M[index].forEach((e,i)=>{
console.log(e);
document.getElementById('result2').innerHTML="<p>["+M+"]</p><br/><p>缺页率:"+(Plist.length-pointPage)/Plist.length+"</p>";//这里用innerHTML最后会被覆盖
})
});
}
Logic3.onclick=()=>{
init();
console.log("LRU");
init();
C=[M[0].length,M[0].length-1,M[0].length-2];
console.log("FIFO");
Plist.forEach((p,i) => {
// debugger;
if(i<=2){ //前三个是一定要产生缺页的,所以直接插入
var w=i;
var stp;
for(w;w>=0;w--){
if(w!=i){
M[i].splice(w,1,B[w]); //当没到和当前p匹配的位置时,前面都是引用上一个的数组的值。
}else{
M[i].splice(w,1,p);
}
} //复杂度是一个m*n的空间复杂度。
B=M[i];
console.log("M["+M[i]+"]");
// M[i+1]=B;//数组是引用类型,这里会将地址统一到m[0]处,这样后面的变了,前面的理所当然的变了,所以说这里不是用引用类型!!!。
// debugger;
}else{//开始判断C,和改变C。//声明一下,如果被命中了,则改处的C的计数从1开始
if(M[i-1].some((value)=>{return value==p;})){//命中了!!这里应该用前一个索引作为当前基准,也就是说不应该是i,应为i是外面的,一直没变。。。
// debugger;
M[i-1].forEach((element,indx) => {
M[i].splice(indx,1,element);
});
C.forEach((e,idx)=>{
if(M[i][idx]==p){
C.splice(idx,1,1);//和fifo的区别处
}else{
C.splice(idx,1,e+1);
}
})//命中每一个前面等待的加1。
pointPage++;
}else{//没命中的话怎么办呢?比较C数组,决定替换最大的那个,
var x=C.indexOf(C.reduce((a,b)=>{return a>b?a:b;}));//找到最先来的是谁。
// debugger;
M[i-1].forEach((element,indx) => {
M[i].splice(indx,1,element);
});
M[i].splice(x,1,p);
C.forEach((e,idx)=>{
C.splice(idx,1,e+1);
});
C.splice(x,1,1);//与此同时被替换的位置则重置为1。
}
}
});
M.forEach((element,index) => {
// debugger;
M[index].forEach((e,i)=>{
console.log(e);
document.getElementById('result3').innerHTML="<p>["+M+"]</p><br/><p>缺页率:"+(Plist.length-pointPage)/Plist.length+"</p>";//这里用innerHTML最后会被覆盖
})
});
}
</script>
</html>