class PAGERANK_MARKING_FAST(page_replacement_algorithm): def __init__(self, N): self.T = Disk(N) self.H = Disk(N) self.N = N self.marked = set() self.G = {} ## local access graph self.last_request = -1 self.first_request = False self.PR = {} def get_N(self) : return self.N def request(self,page) : # print('request: ', page) page_fault = False if not self.first_request : self.__add_edge(self.last_request, page) self.last_request = page self.first_request = False if page in self.T : ## Mark page self.marked.add(page) else : if page in self.H : self.H.delete(page) # Start a new phase when all pages are marked and a page fault occurs # Unmark all the pages if len(self.marked) == self.N : self.marked.clear() self.PR = self.compute_pagerank(page) if self.T.size() == self.N : ## Get the set of unmarked pages U = set(self.T.get_data()) - self.marked # Compute the page rank of all pages # self.PR = self.compute_pagerank(page) ## Choose a page with minimum pagerank least_pagerank_page = -1 for u in U : if least_pagerank_page == -1 or self.PR[u] < self.PR[least_pagerank_page] : least_pagerank_page = u ## Delete page from cache self.T.delete(least_pagerank_page) ## Remove least resent page from history if self.H.size() == self.N : u = self.H.deleteFront() if u is not None and page in self.G : # print('G.pop (',u,')') self.G.pop(u, None) ## Move discarted page to history self.H.add(least_pagerank_page) ## Mark page and add to T self.marked.add(page) self.T.add(page) ## Page fault is True page_fault = True return page_fault def __add_edge(self, u,v) : if u not in self.G : self.G[u] = set() if v not in self.G : self.G[v] = set() self.G[u] = self.G[u] | {v} self.G[v] = self.G[v] | {u} def __get_adj_matrix(self) : ## Mapping node_id = {} node_name = {} for i,node in enumerate(self.G) : node_id[node] = i node_name[i] = node A = np.zeros((len(node_id),len(node_id))) for u in self.G : adj = list(self.G[u]) for v in adj: if v in self.G : u_id = node_id[u] v_id = node_id[v] A[u_id,v_id] = 1 A[v_id,u_id] = 1 else : self.G[u] = self.G[u] - {v} return A,node_id,node_name def __mult_matrix(self,A,n) : B = np.eye(len(A)) while n > 0 : if n % 2 == 1 : B = np.matmul(B,A) A = np.matmul(A,A) n = n / 2 return B def compute_pagerank(self, init_page) : A, node_id, node_name = self.__get_adj_matrix() u = node_id[init_page] n = len(A) ## Transportation vector E = np.zeros(n) E[u] = 1 # ranks_per_page = pr.compute(A,teleport_vector=tv) pr = Pagerank() R = pr.compute_local(A,E) PR = {} for v,pr in enumerate(R) : PR[node_name[v]] = pr return PR def page_label(self,page): lab = "%s(%.1f)" % (page, self.PR[page] if page in self.PR else 0) return lab def page_color(self,page) : if page in self.marked : return 1 ## Red else : return 0 # white def debug(self) : X = [] for u in self.get_data() : X.append((self.P[u],u)) def get_data(self): # data = [] # for i,p,m in enumerate(self.T): # data.append((p,m,i,0)) # return data return [self.T.get_data(), self.H.get_data()]
class ARC(page_replacement_algorithm): def __init__(self, N): self.N = N self.T1 = Disk(N) self.T2 = Disk(N) self.B1 = Disk(N) self.B2 = Disk(2 * N) self.P = 0 self.time = 0 self.X = [] self.Y = [] self.unique = {} self.unique_cnt = 0 self.pollution_dat_x = [] self.pollution_dat_y = [] def getWeights(self): # return np.array([self. X, self.Y1, self.Y2,self.pollution_dat_x,self.pollution_dat_y ]).T return np.array([self.pollution_dat_x, self.pollution_dat_y]).T def getStats(self): d = {} d['pollution'] = np.array([self.pollution_dat_x, self.pollution_dat_y]).T return d def visualize(self, plt): # l1, = plt.plot(self.X,self.Y,'r-', label='ARC p-value') # return [l1] return [] def get_N(self): return self.N def request(self, page): page_fault = False self.time += 1 # self.X.append(self.time) # self.Y.append(1.0*self.P / self.N) t1 = self.T1.size() t2 = self.T2.size() b1 = self.B1.size() b2 = self.B2.size() assert t1 + t2 <= self.N, 'Error: t1+t2 should not be bigger than self.N. t1+t2=%d+%d=%d' % ( t1, t2, t1 + t2) assert t1 + b1 <= self.N, 'Error: t1+b1 should not be bigger than self.N. t1+b1=%d+%d=%d' % ( t1, b1, t1 + b1) assert t1 + t2 + b1 + b2 <= 2 * self.N, 'Error: t1+t2+b1+b2 should not be bigger than 2*self.N. t1+t2+b1+b2=%d+%d+%d+%d=%d' % ( t1, t2, b1, b2, t1 + t2 + b1 + b2) if page in self.T1 or page in self.T2: if page in self.T1: assert self.T1.delete(page) if page in self.T2: assert self.T2.delete(page) assert self.T2.add(page), 'failed adding to T2 at Case 1' elif self.B1.inDisk(page): if self.B2.size() > self.B1.size(): r = self.B2.size() / self.B1.size() else: r = 1 self.P = min(self.P + r, self.N) self.__replace(page) assert self.B1.delete(page) assert self.T2.add(page), 'failed adding to T2 at case B1' page_fault = True elif self.B2.inDisk(page): if self.B1.size() > self.B2.size(): r = self.B1.size() / self.B2.size() else: r = 1 self.P = max(self.P - r, 0) self.__replace(page) assert self.B2.delete(page) assert self.T2.add(page), 'failed adding to T2 at case B2' page_fault = True else: if t1 + b1 == self.N: if t1 < self.N: assert self.B1.deleteFront( ) is not None, 'Error deleting front of B1' self.__replace(page) else: assert self.T1.deleteFront( ) is not None, 'Error deleting front of T1' elif t1 + b1 < self.N: if t1 + t2 + b1 + b2 >= self.N: if t1 + t2 + b1 + b2 == 2 * self.N: assert self.B2.deleteFront( ) is not None, 'Error deleting front of B2' self.__replace(page) # Add page to the MRU position in T1 assert self.T1.add(page), 'failed adding page to T1 at case 4' page_fault = True if page_fault: self.unique_cnt += 1 self.unique[page] = self.unique_cnt if self.time % self.N == 0: pollution = 0 for pg in self.T1.getData() + self.T2.getData(): if self.unique_cnt - self.unique[pg] >= 2 * self.N: pollution += 1 self.pollution_dat_x.append(self.time) self.pollution_dat_y.append(100 * pollution / self.N) return page_fault def __replace(self, x): if self.T1.size() > 0 and (self.T1.size() > self.P or (self.B1.inDisk(x) and self.T1.size() == int(self.P))): y = self.T1.deleteFront() assert y is not None, 'Error deleting front of T1 in replace (Case 1)' assert self.B1.add( y), 'failed adding page to B1 at replace 1(Case 1)' else: y = self.T2.deleteFront() assert y is not None, 'Error deleting front of T2 in replace (Case 2)' assert self.B2.add( y), 'failed adding page to B2 at replace 1(Case 2)' # s1 = self.T1.size()+self.T2.size() # s2 = self.B1.size()+self.B2.size() # print('sizes = %d + %d + %d + %d = %d + %d = %d' % (self.T1.size(),self.T2.size(),self.B1.size(),self.B2.size(), s1,s2,s1+s2)) # print('failed adding at replace 2 %d ' %y) def get_data(self): return [ self.T1.get_data(), self.T2.get_data(), self.B1.get_data(), self.B2.get_data() ] def get_list_labels(self): return ['T1', 'T2', 'B1', 'B2']
class ARCOPT(page_replacement_algorithm): def __init__(self, N, traces): self.T = [] self.N = N self.T1 = Disk(N) self.T2 = Disk(N) self.B1 = Disk(N) self.B2 = Disk(2 * N) self.P = 0 self.page_request_time = {} ## for i, p in enumerate(traces): if p not in self.page_request_time: self.page_request_time[p] = Queue.Queue() self.page_request_time[p].put(i) def get_N(self): return self.N def request(self, page): x = self.page_request_time[page].get() #print self.T1.size(), self.T2.size() page_fault = False #if inList(self.T, page): if self.T1.inDisk(page) or self.T2.inDisk(page): #self.T = moveToMRU(self.T,page) if page in self.T1: self.T1.delete(page) if page in self.T2: self.T2.delete(page) if not self.T2.add(page): print('failed adding at Case 1') elif self.B1.inDisk(page): self.__replace(page) self.B1.delete(page) if not self.T2.add(page): print('failed adding at B1') page_fault = True elif self.B2.inDisk(page): self.__replace(page) self.B2.delete(page) if not self.T2.add(page): print('failed adding at B2') page_fault = True else: t1 = self.T1.size() t2 = self.T2.size() b1 = self.B1.size() b2 = self.B2.size() if t1 + b1 == self.N: if t1 < self.N: self.B1.deleteFront() self.__replace(page) else: self.T1.deleteFront() elif t1 + b1 < self.N: if t1 + t2 + b1 + b2 >= self.N: if t1 + t2 + b1 + b2 == 2 * self.N: self.B2.deleteFront() self.__replace(page) # Add page to the MRU position in T1 # self.T.append(page) if not self.T1.add(page): print('failed adding at case 4') page_fault = True return page_fault def __replace(self, x): if self.T1.size() == 0: y = self.T2.deleteFront() if not y == None: self.B2.add(y) elif self.T2.size() == 0: y = self.T1.deleteFront() if not y == None: self.B1.add(y) else: t1_page = self.T1.getIthPage(0) t2_page = self.T2.getIthPage(0) if not self.page_request_time[t1_page].empty(): page1_time = self.page_request_time[t1_page].queue[0] else: page1_time = int(1e15) if not self.page_request_time[t2_page].empty(): page2_time = self.page_request_time[t2_page].queue[0] else: page2_time = int(1e15) if page1_time > page2_time: y = self.T2.deleteFront() if not y == None: self.B2.add(y) else: y = self.T1.deleteFront() if not y == None: self.B1.add(y) def get_data(self): return [ self.T1.get_data(), self.T2.get_data(), self.B1.get_data(), self.B2.get_data() ] def get_list_labels(self): return ['T1', 'T2', 'B1', 'B2']
class ARC(page_replacement_algorithm): def __init__(self, N): self.T = [] self.N = N self.T1 = Disk(N) self.T2 = Disk(N) self.B1 = Disk(N) self.B2 = Disk(2 * N) self.P = 0 def get_N(self): return self.N def request(self, page): page_fault = False #if inList(self.T, page): if self.T1.inDisk(page) or self.T2.inDisk(page): #self.T = moveToMRU(self.T,page) if page in self.T1: self.T1.delete(page) if page in self.T2: self.T2.delete(page) if not self.T2.add(page): print('failed adding at Case 1') elif self.B1.inDisk(page): if self.B2.size() > self.B1.size(): r = self.B2.size() / self.B1.size() else: r = 1 self.P = min(self.P + r, self.N) self.__replace(page) self.B1.delete(page) if not self.T2.add(page): print('failed adding at B1') page_fault = True elif self.B2.inDisk(page): if self.B1.size() > self.B2.size(): r = self.B1.size() / self.B2.size() else: r = 1 self.P = min(self.P - r, 0) self.__replace(page) self.B2.delete(page) if not self.T2.add(page): print('failed adding at B2') page_fault = True else: t1 = self.T1.size() t2 = self.T2.size() b1 = self.B1.size() b2 = self.B2.size() if t1 + b1 == self.N: if t1 < self.N: self.B1.deleteFront() self.__replace(page) else: self.T1.deleteFront() elif t1 + b1 < self.N: if t1 + t2 + b1 + b2 >= self.N: if t1 + t2 + b1 + b2 == 2 * self.N: self.B2.deleteFront() self.__replace(page) # Add page to the MRU position in T1 # self.T.append(page) if not self.T1.add(page): print('failed adding at case 4') page_fault = True return page_fault def __replace(self, x): if self.T1.size() > 0 and (self.T1.size() > self.P or (self.B1.inDisk(x) and self.B1.size() == self.P)): y = self.T1.deleteFront() if not y == None: if not self.B1.add(y): print('failed adding at replace 1') else: y = self.T2.deleteFront() if not y == None: if not self.B2.add(y): print('sizes = %d %d %d %d' % (self.T1.size(), self.T2.size(), self.B1.size(), self.B2.size())) print('failed adding at replace 2 %d ' % y) def get_data(self): return [ self.T1.get_data(), self.T2.get_data(), self.B1.get_data(), self.B2.get_data() ] def get_list_labels(self): return ['T1', 'T2', 'B1', 'B2']
class WALK_MARKING_SLOW(page_replacement_algorithm): def __init__(self, N): self.T = Disk(N) self.H = Disk(N) self.N = N self.marked = set() self.G = {} ## local access graph self.is_first_request = True self.last_request = -1 self.page_probability = {} def get_N(self): return self.N def request(self, page): # print('request: ', page) page_fault = False if not self.is_first_request: self.__add_edge(self.last_request, page) self.last_request = page self.is_first_request = False if page in self.T: ## Mark page self.marked.add(page) else: if page in self.H: self.H.delete(page) # Start a new phase when all pages are marked and a page fault occurs # Unmark all the pages if len(self.marked) == self.N: self.marked.clear() if self.T.size() == self.N: self.page_probability = self.__calculate_prob(page) ## Get the set of unmarked pages U = set(self.T.get_data()) - self.marked U_list = list(U) U_dist = [] for u in U_list: U_dist.append(self.page_probability[u]) page_to_evict = random_select_page(U_list, U_dist) ## Delete page from cache self.T.delete(page_to_evict) ## Remove least resent page from history if self.H.size() == self.N: hist_lru = self.H.deleteFront() if hist_lru is not None and hist_lru in self.G: self.G.pop(hist_lru, None) ## Move discarted page to history self.H.add(page_to_evict) ## Mark page and add to T self.marked.add(page) self.T.add(page) ## Page fault is True page_fault = True return page_fault def __add_edge(self, u, v): if u not in self.G: self.G[u] = set() if v not in self.G: self.G[v] = set() self.G[u] = self.G[u] | {v} self.G[v] = self.G[v] | {u} def get_adj_matrix(self): ## Mapping node_id = {} node_name = {} for i, node in enumerate(self.G): node_id[node] = i node_name[i] = node A = np.zeros((len(node_id), len(node_id))) for u in self.G: adj = list(self.G[u]) for v in adj: if v in self.G: u_id = node_id[u] v_id = node_id[v] A[u_id, v_id] = 1 A[v_id, u_id] = 1 else: self.G[u] = self.G[u] - {v} ## Normalize for u in range(len(A)): degree = np.sum(A[u, :]) if degree > 0: A[u, :] /= degree return A, node_id, node_name def __calculate_prob(self, init_page): A, node_id, node_name = self.get_adj_matrix() u = node_id[init_page] n = len(A) M = Markov(A) R = M.random_walk_distribution(u) # print('R = ',R) P = {} for u, p in enumerate(R): # print('PR[%s] = %f' % (node_name[u], pr)) P[node_name[u]] = p return P ###################################################################################################################################### def page_label(self, page): lab = "%s(%.1f)" % (page, self.page_probability[page] if page in self.page_probability else 0) return lab def page_color(self, page): if page in self.marked: return 1 ## Red else: return 0 # white def debug(self): X = [] for u in self.get_data(): X.append((self.P[u], u)) def get_data(self): # data = [] # for i,p,m in enumerate(self.T): # data.append((p,m,i,0)) # return data return [self.T.get_data()]
class TWO_LIST_MARKING: def __init__(self, N): self.M1 = Disk(N) self.M2 = Disk(N) self.U1 = Disk(N) self.U2 = Disk(N) self.B1 = Disk(N) self.B2 = Disk(N) self.P = 0 self.N = N def get_N(self): return self.N def request(self, page): pageFault = False if self.M1.inDisk(page) or self.M2.inDisk(page) or self.U1.inDisk( page) or self.U2.inDisk(page): ## Remove from the list self.M1.delete(page) self.M2.delete(page) self.U1.delete(page) self.U2.delete(page) ## Move to M2 self.M2.add(page) else: pageFault = True ## Start a new phase when all pages are marked and a page fault occurs if self.M1.size() + self.M2.size() == self.N: m1_data = self.M1.getData() m2_data = self.M2.getData() for x in m1_data: self.M1.delete(x) self.U1.add(x) for x in m2_data: self.M2.delete(x) self.U2.add(x) ## If page is in history then update P ## u = u1 + u2 ## 0 <= p <= u / u1 ## p(u1) = p / u ## p(u2) = (u - p*u1)/(u*u2) u1 = self.U1.size() u2 = self.U2.size() u = u1 + u2 if self.B1.inDisk(page): if u1 > 0: self.P += 1.0 * u2 / u1 else: self.P += 0.5 if u1 > 0 and self.P > (u / u1): self.P = (u / u1) self.B1.delete(page) elif self.B2.inDisk(page): if u2 > 0: self.P -= 1.0 * u1 / u2 else: self.P -= 0.5 if self.P < 0: self.P = 0 self.B2.delete(page) if self.M1.size() + self.M2.size() + self.U1.size() + self.U2.size( ) == self.N: # Evict a page U1 = self.U1.getData() U2 = self.U2.getData() if u1 == 0: p1 = 0 p2 = 1.0 / u elif u2 == 0: p1 = 1.0 / u p2 = 0 else: p1 = self.P / u # Probability of choosing a page in U1 p2 = (u - self.P * u1) / ( u * u2) # Probability of choosing a page in U2 ## Calculate probability distribution P = [0 for i in range(0, self.N)] for i, u in enumerate(U1): P[i] = p1 if i > 0: P[i] += P[i - 1] for i, u in enumerate(U2): P[i + u1] = p2 if i + u1 > 0: P[i + u1] += P[i + u1 - 1] ## Choose a page a random ran = random.random() U = U1 + U2 for i, u in enumerate(U): if ran < P[i]: self.U1.delete(u) self.U2.delete(u) evicted = u if i < u1: inU1 = True else: inU1 = False break if inU1: if self.B1.size() == self.N: self.B1.deleteFront() self.B1.add(evicted) else: if self.B2.size() == self.N: self.B2.deleteFront() self.B2.add(evicted) ## Add new page to M1 self.M1.add(page) return pageFault def getData(self): m1 = [] m2 = [] u1 = [] u2 = [] b1 = [] b2 = [] for m in self.M1.getData(): m1.append((m, 1)) for m in self.M2.getData(): m2.append((m, 3)) for u in self.U1.getData(): u1.append((u, 0)) for u in self.U2.getData(): u2.append((u, 2)) for m in self.B1.getData(): b1.append(m) for m in self.B2.getData(): b2.append(m) return [u1 + m1 + u2 + m2, b1, b2]
class HIT_MARKING(page_replacement_algorithm): def __init__(self, N): self.T = Disk(N) self.H = Disk(N) self.N = N self.marked = set() self.G = Graph() ## local access graph self.is_first_request = True self.last_request = -1 self.hitting_time = {} self.fast_mode = True self.use_weights = False self.weights = {} def request(self, page): # print('request: ', page) page_fault = False if not self.is_first_request: self.G.increase_edge_weight(self.last_request, page, 1) self.last_request = page self.is_first_request = False if page in self.T: ## Mark page self.marked.add(page) else: # Start a new phase when all pages are marked and a page fault occurs # Unmark all the pages if len(self.marked) == self.N: self.marked.clear() if self.fast_mode is True: self.hitting_time = self.__calculate_hit_time(page) if self.T.size() == self.N: if self.fast_mode is False: self.hitting_time = self.__calculate_hit_time(page) ## Get the set of unmarked pages U = set(self.T.get_data()) - self.marked U_list = list(U) U_dist = [] for u in U_list: U_dist.append(self.page_probability[u]) page_to_evict = random_select_page(U_list, U_dist) ## Delete page from cache self.T.delete(page_to_evict) ## Remove least resent page from history if self.H.size() == self.N: hist_lru = self.H.deleteFront() if hist_lru is not None and hist_lru in self.G: self.G.pop(hist_lru, None) ## Mark page and add to T self.marked.add(page) self.T.add(page) ## Page fault is True page_fault = True return page_fault def __calculate_hit_time(self, init_page): A, node_id, node_name = self.G.get_adj_matrix() ####################### ## Hitting time ####################### # print('R = ',R) m = self.G.number_vertices() m = self.G.number_edges() P = {} for u, p in enumerate(R): # print('PR[%s] = %f' % (node_name[u], pr)) P[node_name[u]] = p return P ###################################################################################################################################### def page_label(self, page): lab = "%s(%.1f)" % (page, self.page_probability[page] if page in self.page_probability else 0) return lab def page_color(self, page): if page in self.marked: return 1 ## Red else: return 0 # white def debug(self): X = [] for u in self.get_data(): X.append((self.P[u], u)) def get_data(self): # data = [] # for i,p,m in enumerate(self.T): # data.append((p,m,i,0)) # return data return [self.T.get_data()]