【文末送书】LRU 淘汰算法

目录

  • 1. LRU 淘汰算法
    • 1.1 定义
    • 1.2 实例化
    • 1.3 增加或更新
    • 1.4 查询
    • 1.5 删除
  • 送书

【文末送书】LRU 淘汰算法_第1张图片

1. LRU 淘汰算法

LRU(Least Recently Used)

LRULeast Recently Used的缩写,即最近最少使用页面置换算法,是为虚拟页式存储管理服务的,是根据页面调入内存后的使用情况进行决策了。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU算法就是将最近最久未使用的页面予以淘汰。

1.1 定义

  • 定义结构体
type Cache struct {
	maxBytes int64   	  //允许使用的最大内存
	Nbytes   int64		  //当前已使用的内存
	ll       *list.List   //双向列表
	cache    map[string]*list.Element  
	//键是字符串,值是双向链表中对应节点的指针
	OnEvicted func(key string, value Value)
	//是某条记录被`移除`时的回调函数,可以为 nil。
}

// Value use Len to count how many bytes it takes
/*
使用Len来计算需要多少个字节
允许值是实现了 Value 接口的任意类型

该接口只包含了一个方法 Len() int,用于返回值所占用的内存大小。
*/
type Value interface {
	Len() int
}

1.2 实例化

  • 实例化这个Cache对象,使之可以New出来。
// 对于Cache进行了实例化,能New一个Cache出来。
func New(maxBytes int64, onEvicted func(string, Value)) *Cache {
	return &Cache{
		maxBytes:  maxBytes,  
		ll:        list.New(),
		cache:     make(map[string]*list.Element),
		OnEvicted: onEvicted,
	}
}

1.3 增加或更新

  • 增加或更新缓存
func (c *Cache) Add(key string, value Value) {
	if ele, ok := c.cache[key]; ok {
		c.ll.MoveToFront(ele)  		//这个键存在,移动到队尾
		kv := ele.Value.(*entry)	
		//kv 是值, 因为value是接口, 
		//因此类型断言设置为*entry
		c.Nbytes += int64(value.Len()) - int64(kv.value.Len()) 
		// 计算现在的缓存,以至于将其中的
		kv.value = value
	} else {
		ele := c.ll.PushFront(&entry{key, value}) //没有的话,就创建这一个键值对
		c.cache[key] = ele
		c.Nbytes += int64(len(key)) + int64(value.Len())
	}

	for c.maxBytes != 0 && c.maxBytes < c.Nbytes {	
		// 如果超出缓存容量
		c.RemoveOldest()							
		// 那么移除双向链表中的最后一项
	}
}

1.4 查询

  • 获取缓存里面的值
// Get look ups a key's value
func (c *Cache) Get(key string) (value Value, ok bool) {
	if ele, ok := c.cache[key]; ok { 
		// 如果这个需要查找的值是存在的,则将对应的节点移动到队尾,并返回查找到的值
		c.ll.MoveToFront(ele)
		// 双向链表作为队列,队首队尾是相对的,在这里约定 front 为队尾
		kv := ele.Value.(*entry)
		return kv.value, true
	}
	return
}

1.5 删除

  • 删除缓存(被淘汰)
// RemoveOldest removes the oldest item
//这里的删除,实际上是缓存淘汰。即移除最近最少访问的节点(队首)
func (c *Cache) RemoveOldest() {
	ele := c.ll.Back()    //取到队首节点
	if ele != nil {
		c.ll.Remove(ele)  //从链表中删除
		kv := ele.Value.(*entry)  //获取值
		delete(c.cache, kv.key)  //从字典 c.cache 中删除该节点的映射关系。
		c.Nbytes -= int64(len(kv.key)) + int64(kv.value.Len()) //计算这里大小
		if c.OnEvicted != nil {
			c.OnEvicted(kv.key, kv.value)
		}
	}
}

由于这种方法是无法支持并发的,因为一旦多个线程进行竞争,就会导致写入顺序与读取顺序的混乱
这就是竞争资源,我们可以加锁去优化这一个缓存机制。

送书

这一周送两本书,点赞或是评论都可以参与哈~

本书以零基础讲解为宗旨,面向学习数据科学与人工智能的读者,通俗地讲解每一个知识点,旨在帮助读者快速打下数学基础。

全书分为 4 篇,共 17 章。其中第 1 篇为数学知识基础篇,主要讲述了高等数学基础、微积分、泰勒公式与拉格朗日乘子法;第 2 篇为数学知识核心篇,主要讲述了线性代数基础、特征值与矩阵分解、概率论基础、随机变量与概率估计;第 3 篇为数学知识提高篇,主要讲述了数据科学的几种分布、核函数变换、熵与激活函数;第 4 篇为数学知识应用篇,主要讲述了回归分析、假设检验、相关分析、方差分析、聚类分析、贝叶斯分析等内容。

本书适合准备从事数据科学与人工智能相关行业的读者。

【文末送书】LRU 淘汰算法_第2张图片

硬件产品开发是一项复杂的工程,涉及产品定义、成本控制、质量管理、进度管理、研发管理、生产管控、供应链管理和售后服务等多个环节。合理的流程可以化繁为简,提升沟通及合作效率,降低风险,确保项目按计划交付。

本书分为10个章节,分别对硬件产品开发过程中的各个关键环节进行了详细的介绍。每个环节都有相应的模板和说明,并且通过实际案例来说明流程的重要性和使用方法,旨在帮助硬件工程师和初创团队更快地熟悉和掌握开发流程。

【文末送书】LRU 淘汰算法_第3张图片
没有抽到的同学,我每周都会送书的,也可以在这里购买奥~

当当自营购买链接:
http://product.dangdang.com/29418231.html
http://product.dangdang.com/29145839.html

你可能感兴趣的:(遇见Golang,拥抱未来,算法)