存儲管理的主要功能之一是合理地分配空間。請求頁式管理是一種經常使用的虛擬存儲管理技術。html
此次的目的是經過請求頁式管理中頁面置換算法模擬設計,瞭解虛擬存儲技術的特色,掌握請求頁式存儲管理的頁面置換算法。java
要求以下算法
(1)
經過計算不一樣算法的命中率比較算法的優劣。同時也考慮了用戶內存 容量對命中率的影響。 命中率 1 頁面失效次數 頁地址流長度 頁面失效次數爲每次訪問相應指令時,該指令所對應的頁不在內存中 的次數。 在本實驗中,假定頁面大小爲 1k,用戶虛存容量爲 32k,用戶內存容 量爲 4 頁到 32 頁。 (2) produce_addstream 經過隨機數產生一個指令序列,共 320 條指令。 A、 指令的地址按下述原則生成: 1) 50%的指令是順序執行的 2)25%的指令是均勻分佈在前地址部分 3) 25%的指令是均勻分佈在後地址部分 10 B、 具體的實施方法是: 1) 在[0,319]的指令地址之間隨機選取一塊兒點 m; 2) 順序執行一條指令,即執行地址爲 m+1 的指令; 3) 在前地址[0,m+1]中隨機選取一條指令並執行,該指令的地 址爲 m’; 4) 順序執行一條指令,地址爲 m’+1 的指令 5) 在後地址[m’+2,319]中隨機選取一條指令並執行; 6) 重複上述步驟 1)~5),直到執行 320 次指令 C、 將指令序列變換稱爲頁地址流 在用戶虛存中,按每 k 存放 10 條指令排列虛存地址,即 320 條指令在 虛存中的存放方式爲: 第 0 條~第 9 條指令爲第 0 頁(對應虛存地址爲[0,9]); 第 10 條~第 19 條指令爲第 1 頁(對應虛存地址爲[10,19]); 。。。。。。 第 310 條~第 319 條指令爲第 31 頁(對應虛存地址爲[310,319]); 按以上方式,用戶指令可組成 32 頁。 (3)計算並輸出下屬算法在不一樣內存容量下的命中率。 1)先進先出的算法(FIFO); 2)最近最少使用算法(LRU); 3)最佳淘汰算法(OPT); 4)最少訪問頁面算法(LFR);
下面給出Java代碼的實現dom
import java.util.*; public class A { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("Start memory management.\r\n"+"Producing address flow, wait for while, please. "); produce_addstream(); for(int a:stream) { System.out.print(a+" "); } System.out.println("\r\nThere are algorithms in the program \r\n一、 Optimization algorithm\r\n" + "二、 Least recently used algorithm\r\n" + "三、 First in first out algorithm\r\n" + "四、 Least frequently used algorithm Select an algorithm number, please.\r\n"); int Num = sc.nextInt(); switch(Num) { case 3: FIFO(3); break; case 2: LRU(3); break; case 1: OPT(3); break; case 4: LFU(3); break; default: System.out.println("there is not the algorithm in the program"); break; } System.out.println("do you try again with anther algorithm(y/n)"); for(int i=2;i<32;i++) { System.out.println("---Msize="+i+"------"); FIFO(i); LRU(i); OPT(i); LFU(i); } } static List<Integer> stream; /** * @return 產生指令序列stream */ public static void produce_addstream(){ stream=new ArrayList<>(); do { int m = (int)((Math.random()*319));//起點 stream.add(m+1);//執行m+1 int m2 = (int)((Math.random()*(m+1))); stream.add(m2);//執行m2 stream.add(m2+1);//執行m2+1 int m3 = (m2+2)+(int)(+Math.random()*(319-m2-2)); stream.add(m3);//執行[m2+2,319] }while(stream.size()<=320); } /** * 根據指令數找到頁面 * @param zhiLing 所需指令 * @return 指令所在頁面 */ public static int search(int zhiLing) { return zhiLing/10; } /** * 先進先出 * @param Msize 物理塊數 */ public static void FIFO(int Msize) { Queue<Integer> que = new LinkedList<>(); Double C = 0.0;//未命中次數 for(int i=0;i<stream.size();i++) { int zhiLing = stream.get(i); int yeMian = search(zhiLing); if(que.contains(yeMian)) { }else { C++; if(que.size()==Msize) { que.poll(); } que.offer(yeMian); } } C-=Msize; Double c = 1-(double) (C/320); System.out.println("FIFO: "+String.format("%.6f",c)+" Msize : "+Msize); } /** * 最近最久未使用算法 * @param Msize 物理塊 */ public static void LRU(int Msize) { Stack<Integer> stack = new Stack<>(); Double C = 0.0;//未命中次數 for(int i=0;i<stream.size();i++) { int zhiLing = stream.get(i); int yeMian = search(zhiLing); if(stack.contains(yeMian)) { stack.removeElement(yeMian); stack.push(yeMian); }else { C++; if(stack.size()==Msize) { stack.removeElement(stack.firstElement()); } stack.push(yeMian); } } C-=Msize; Double c = 1-(double) (C/320); System.out.println("LRU : "+String.format("%.6f",c)+" Msize : "+Msize); } /** * 最佳置換算法 * @param Msize 物理塊 */ public static void OPT(int Msize) { Double C = 0.0;//未命中次數 Set<Integer> set = new HashSet<>(); for(int i=0;i<stream.size();i++) { int zhiLing = stream.get(i); int yeMian = search(zhiLing); if(set.contains(yeMian)) { }else { C++; if(set.size()==Msize) { int max = -1;//最長時間不會使用的指令的頁面 int[] temp = new int[32]; for(int a:set) { for(int j=i+1;j<stream.size();j++) { if(search(stream.get(j))==a) { temp[a]=j; break; } } } for(int a:set) { if(max==-1) max=a; if(temp[a]==0) { set.remove(a); break; } if(temp[a]>temp[max]) max=a; } if(set.size()==Msize) { set.remove(max);//移除該頁面 } } set.add(yeMian); } } C-=Msize; Double c = 1-(double) (C/320); System.out.println("OPT : "+String.format("%.6f",c)+" Msize : "+Msize); } /** * 最少使用置換算法 * @param Msize */ public static void LFU(int Msize) { Double C = 0.0;//未命中次數 Set<Integer> set = new HashSet<>(); for(int i=0;i<stream.size();i++) { int zhiLing = stream.get(i); int yeMian = search(zhiLing); int[] temp = new int[32]; if(set.contains(yeMian)) { }else { C++; if(set.size()==Msize) { int Min = -1; for(int a:set) { for(int j=i-1;j>=0;j--) { if(search(stream.get(j))==a) { temp[a]=j; break; } } } for(int a:set) { if(Min==-1) { Min=a; continue; } if(temp[a]<temp[Min]) { Min=a; } } set.remove(Min);//移除該頁面 } set.add(yeMian); temp[yeMian]++; } } C-=Msize; Double c = 1-(double) (C/320); System.out.println("LFU : "+String.format("%.6f",c)+" Msize : "+Msize); } }
(1) 經過計算不一樣算法的命中率比較算法的優劣。同時也考慮了用戶內存ide
容量對命中率的影響。spa
命中率 =1-設計 |
頁面失效次數code |
|
頁地址流長度orm |
|
|
|
|
頁面失效次數爲每次訪問相應指令時,該指令所對應的頁不在內存中htm
的次數。
在本實驗中,假定頁面大小爲 1k,用戶虛存容量爲 32k,用戶內存容
量爲 4頁到 32頁。
(2) produce_addstream 經過隨機數產生一個指令序列,共 320 條指令。
A、指令的地址按下述原則生成:
1) 50%的指令是順序執行的
2)25%的指令是均勻分佈在前地址部分
3) 25%的指令是均勻分佈在後地址部分
10
1) 在[0,319]的指令地址之間隨機選取一塊兒點 m;
2) 順序執行一條指令,即執行地址爲 m+1的指令;
3) 在前地址[0,m+1]中隨機選取一條指令並執行,該指令的地
址爲 m’;
4) 順序執行一條指令,地址爲 m’+1的指令
5) 在後地址[m’+2,319]中隨機選取一條指令並執行;
6) 重複上述步驟 1)~5),直到執行 320次指令
C、 將指令序列變換稱爲頁地址流
在用戶虛存中,按每 k存放 10條指令排列虛存地址,即 320條指令在
虛存中的存放方式爲:
第 0條~第 9條指令爲第 0頁(對應虛存地址爲[0,9]);
第 10 條~第 19 條指令爲第 1 頁(對應虛存地址爲[10,19]);
。。。。。。
第 310 條~第 319 條指令爲第 31 頁(對應虛存地址爲[310,319]);
按以上方式,用戶指令可組成 32頁。
(3)計算並輸出下屬算法在不一樣內存容量下的命中率。
1)先進先出的算法(FIFO);
2)最近最少使用算法(LRU);
3)最佳淘汰算法(OPT);
4)最少訪問頁面算法(LFR);