《业务开发算法50讲》学习笔记Day3

140 阅读3分钟

《15|LRU: 在虚拟内存中页面是如何置换的?》

操作系统的缓存淘汰

操作系统的一大作用,就是通过虚拟和抽象为应用开发者提供了一套操作系统硬件的统一接口(PS: 感觉有点像Java的Log日志亦或是JDBC...)

操作系统的分页机制, 让用户无需关心物理内存的管理和容量, 通过虚拟内存和分页机制, 用户可以在一个大而连续的逻辑地址和非连续的物理地址之间, 建立起映射

但内存容量并不是无限的, 访问到不在内存中的其他页, 硬件会触发“缺页中断”, 操作系统会在内存中选出一个页, 把它替换成需要访问的目标页.

这种场景在各种缓存的系统中也很常见, 如缓存中间件Redis的内存淘汰算法

具体的置换策略

有如下置换策略

随机页面置换算法

随机获取一个内存中页, 进行替换

缺点: 没有用到任何历史访问记录的信息, 不稳定, 而历史信息是很有用的, 也是我们唯一能用于优化命中率的依据

最优页面置换算法

在置换页面的时候, 永远优先替换内存中最久不被访问的那个页面, 尽可能晚地触发缺页中断

问题: 无法真正被实现, 在程序运行时, 并没有很好的办法去预测之后访问的页码是哪些, 仅供参考.

FIFO算法

First In, First Out. 在每次缺页中断时, 替换当前物理内存中最早被加入缓存的页

缺点: 先加入的页面可能会被多次访问, 如果经常让更早被加入但访问频繁的页面淘汰, 显然不是一个很好的策略. 这意味着我们不但要使用历史数据, 还要更好地设计利用的方式, 让策略更接近于最优算法

LRU算法

Least Recently Used, 最近最少置换算法, 由于引用序列有明显的局部相关性,每个出现的页码有比较高的概率会在相邻的一段时间里反复出现, 如果某个页码在过去访问过, 就尽量晚点去淘汰它

具体实现

之前也学习过LRU的实现, 也写过一篇, LRU淘汰算法实现, 主要是通过双向链表+散列表实现, 感兴趣的可以点击查看

总结

通过分页和虚拟内存的抽象,操作系统解放了用户对内存管理和容量的心智负担。当缓存的数据越来越多,如何选择一个合适的页面或缓存内容来替换,就是缓存置换算法的用武之地。

要理解置换策略(ps: 也可以延伸至很多系统的算法的实现), 都需要有扎实的数据结构和算法基础, 我们一定要好好学习!