• 『码农翻身』高速缓存置换策略


    计算机高速缓存

    • 字:是指存放在一个存储单元中的二进制代码的组合
    • 字块:存储在连续的存储单元中而被看作是一个单元的一组字

    高速缓存由多个字块组成

    高速缓存的替换策略

    先进先出算法(FIFO)

    • 把高速缓存看作是一个先进先出的队列
    • 优先替换最先进入队列的字块

    最不经常使用算法(LFU)

    • 优先淘汰最不经常使用的字块
    • 需要额外的空间记录字块的使用频率

    最近最少使用算法(LRU)

    • 优先淘汰一段时间内没有使用的字块
    • 有多种实现方法,一般使用双向链表

    页面置换算法的实现

    双向链表

    from typing import Any, Union
    
    
    class Node(object):
    
        def __init__(self, key: Any, value: Any):
            self.key: Any = key
            self.value: Any = value
            self.prev: Node = None
            self.next: Node = None
    
        def __str__(self):
            val = f"{{{self.key}:{self.value}}}"
            return val
    
        def __repr__(self):
            val = f"{{{self.key}:{self.value}}}"
            return val
    
    
    class LFUNode(Node):
    
        def __init__(self, key: Any, value: Any):
            super().__init__(key, value)
            self.freq: int = 0
    
    
    class LinkedList(object):
    
        def __init__(self, capacity: int = 0xffff):
            self.capacity: int = capacity
            self.head: Union[Node, LFUNode] = None
            self.tail: Union[Node, LFUNode] = None
            self.size: int = 0
    
        # 从头部添加结点
        def __add_head(self, node: Union[Node, LFUNode]) -> Union[Node, LFUNode]:
            if not self.head:
                self.head = node
                self.tail = node
                self.head.prev = None
                self.tail.next = None
            else:
                node.next = self.head
                self.head.prev = node
                self.head = node
                self.head.prev = None
    
            self.size += 1
    
            return node
    
        # 从尾部添加结点
        def __add_tail(self, node: Union[Node, LFUNode]) -> Union[Node, LFUNode]:
            if not self.tail:
                self.tail = node
                self.head = node
                self.tail.next = None
                self.head.prev = None
            else:
                node.prev = self.tail
                self.tail.next = node
                self.tail = node
                self.tail.next = None
    
            self.size += 1
    
            return node
    
        def __del_tail(self) -> Union[Node, LFUNode, None]:
            if not self.tail:
                return
    
            node = self.tail
            if node.prev:
                self.tail = node.prev
                self.tail.next = None
            else:
                self.head = self.tail = None
    
            self.size -= 1
    
            return node
    
        def __del_head(self) -> Union[Node, LFUNode, Node]:
            if not self.head:
                return
    
            node = self.head
    
            if node.next:
                self.head = node.next
                self.head.prev = None
            else:
                self.head = self.tail = None
    
            self.size -= 1
    
            return node
    
        # 任意结点删除
        def __remove(self, node: Union[Node, LFUNode]) -> Union[Node, LFUNode, None]:
            if self.size <= 0:
                raise ValueError("链表为空!")
            if not node:
                node = self.tail
    
            if node == self.tail:
                self.__del_tail()
            elif node == self.head:
                self.__del_head()
            else:
                node.prev.next = node.next
                node.next.prev = node.prev
                self.size -= 1
    
            return node
    
        def pop(self) -> Union[Node, LFUNode, None]:
            return self.__del_head()
    
        def append(self, node: Union[Node, LFUNode]) -> Union[Node, LFUNode]:
            return self.__add_tail(node)
    
        def append_front(self, node: Union[Node, LFUNode]) -> Union[Node, LFUNode]:
            return self.__add_head(node)
    
        def remove(self, node: Union[Node, LFUNode] = None) -> Union[Node, LFUNode, None]:
            return self.__remove(node)
    
        def print(self):
            """调试用"""
            p = self.head
            line = ""
            while p:
                line += f"{p}"
                p = p.next
                if p:
                    line += "=>"
            print(line)
            
    

    FIFO 算法

    from typing import Any, Union, Dict
    
    from LinkedList import LinkedList, Node
    
    
    class FIFOCache(object):
    
        def __init__(self, capacity: int):
            self.capacity: int = capacity
            self.size: int = 0
            self.map: Dict[Any, Node] = {}
            self.list: LinkedList[Node] = LinkedList(capacity)
    
        def get(self, key: Any) -> Union[int, Any]:
            if key not in self.map:
                return -1
            else:
                node = self.map[key]
                return node.value
    
        def put(self, key: Any, value: Any):
            if self.capacity == 0:
                return
            if key in self.map:
                node = self.map[key]
                self.list.remove(node)
                node.value = value
                self.list.append(node)
            else:
                if self.size == self.capacity:
                    node = self.list.pop()
                    del self.map[node.key]
                    self.size -= 1
                node = Node(key, value)
                self.list.append(node)
                self.map[key] = node
                self.size += 1
    
        def print(self):
            """调试用"""
            self.list.print()
            
    

    LFU 算法

    from typing import Any, Dict, Union
    
    from LinkedList import LFUNode, LinkedList
    
    
    class LFUCache(object):
    
        def __init__(self, capacity: int):
            self.capacity: int = capacity
            self.map: Dict[Any, LFUNode] = {}
            self.freq_map: Dict[int, LinkedList] = {}  # key 是频率, value 是对应的双向链表
            self.size: int = 0
    
        def __update_freq(self, node: LFUNode):
            freq = node.freq
    
            node = self.freq_map[freq].remove(node)
    
            if self.freq_map[freq].size == 0:
                del self.freq_map[freq]
    
            freq += 1
            node.freq = freq
    
            if freq not in self.freq_map:
                self.freq_map[freq] = LinkedList()
    
            self.freq_map[freq].append(node)
    
        def get(self, key: Any) -> Union[int, Any]:
            if key not in self.map:
                return -1
            node = self.map[key]
            self.__update_freq(node)
            return node.value
    
        def put(self, key: Any, value: Any):
            if self.capacity == 0:
                return
    
            if key in self.map:
                node = self.map[key]
                node.value = value
                self.__update_freq(node)
    
            else:
                if self.capacity == self.size:
                    min_freq = min(self.freq_map)
                    node = self.freq_map[min_freq].pop()
                    del self.map[node.key]
                    self.size -= 1
    
                node = LFUNode(key, value)
                node.freq = 1
                self.map[key] = node
                if node.freq not in self.freq_map:
                    self.freq_map[node.freq] = LinkedList()
                node = self.freq_map[node.freq].append(node)
                self.size += 1
    
        def print(self):
            print("****************************************")
            for k in self.freq_map:
                print(f"freq = {k}")
                self.freq_map[k].print()
            print("****************************************")
            print()
            
    

    LRU 算法

    from typing import Any, Union, Dict
    
    from LinkedList import Node, LinkedList
    
    
    class LRUCache(object):
    
        def __init__(self, capacity: int):
            self.map: Dict[Any, Node] = {}
            self.list: LinkedList[Node] = LinkedList(capacity)
    
        def get(self, key: Any) -> Union[int, Any]:
            if key in self.map:
                node = self.map[key]
                self.list.remove(node)
                self.list.append_front(node)
                return node.value
            else:
                return -1
    
        def put(self, key: Any, value: Any):
            if key in self.map:
                node = self.map[key]
                self.list.remove(node)
                node.value = value
                self.list.append_front(node)
            else:
                node = Node(key, value)
                # 如果链表缓存已满
                if self.list.size >= self.list.capacity:
                    old_node = self.list.remove()
                    self.map.pop(old_node.key)
    
                self.list.append_front(node)
                self.map[key] = node
    
        def print(self):
            self.list.print()
            
    
  • 相关阅读:
    stream流
    python笔记:str.contains小坑之 UserWarning To actually get the groups, use str.extract.
    获取excel的行索引值
    Pandas学习(4、数据载入、存储及文件格式
    python中如何压缩和解压缩文件
    保持服务器屏幕可控制状态
    python判断文件和文件夹是否存在、创建文件夹
    PDF处理
    selenium+python配置chrome浏览器的选项
    python实现复制粘贴
  • 原文地址:https://www.cnblogs.com/ice-coder/p/12728991.html
Copyright © 2020-2023  润新知