Unity学习笔记--使用 C# 开发一个 LRU

目录

      • 什么是 LRU
      • LRU 核心思想
      • 代码实现一:双向链表 + 哈希表
      • 分析
      • 代码实现二:OrderedDictionary
      • 分析
      • 项目案例
      • 预告
      • 结尾

什么是 LRU

在计算机系统中,LRU(Least Recently Used,最近最少使用)是一种缓存置换算法。缓存是计算机系统中的一种能够高速获取数据的介质,而缓存置换算法则是在缓存空间不足时,需要淘汰掉部分缓存数据以腾出空间,使得后来需要访问数据能够有更多的缓存空间可用。

LRU 算法将缓存中的数据分为“热数据”和“冷数据”,热数据是经常使用的数据,而冷数据很少使用。当缓存满了并有新数据需要加入缓存时,我们就需要通过LRU算法从缓存中淘汰一些数据,那么就淘汰最久未被访问的数据,也就是“冷数据”,而把“热数据”保留在缓存中,因为“热数据”很可能还会被使用,这样就能有效地提高了缓存的命中率,减少了内存的使用量,优化了系统的性能。

用通俗的话来说就是最近被频繁访问的数据会具备更高的留存,淘汰那些不常被访问的数据。

LRU 核心思想

LRU 的核心思想是“时间局部性原理”。这个原理表明在一段时间内程序访问的数据,很大概率在不久的将来还会访问,因此很可能被缓存起来。而很长时间不被访问的数据,很可能在不久的将来也不会被访问,因此被淘汰掉的概率很大。基于这个原理,LRU 算法要在缓存不够用时,先把缓存中很久没有被使用的数据替换掉,以此保证更常用的数据在缓存中,提高缓存的命中率。

具体来说,在缓存对象中使用一个链表来维护缓存数据的顺序,每当缓存对象被使用时,将该数据从链表中移到链表末尾,每当缓存对象满时,将链表头部的数据淘汰。

这样保证了链表尾部的数据是最近被使用的数据,链表头部的数据是最久未被使用的,这样就可以通过移动链表节点来维护数据在缓存中的顺序,并淘汰链表头部的数据来保证缓存大小不大于某个限度,从而达到提高缓存命中率的目的。因此,LRU 算法的核心思想就是“淘汰最久未被使用的数据,保留近期最少使用的数据”,以此来优化系统的性能。

代码实现一:双向链表 + 哈希表

using System.Collections.Generic;public class LRUCache<K, V>
{private int capacity;private Dictionary<K, LinkedListNode<Tuple<K, V>>> dict;private LinkedList<Tuple<K, V>> linkedList;public LRUCache(int capacity){this.capacity = capacity;this.dict = new Dictionary<K, LinkedListNode<Tuple<K, V>>>();this.linkedList = new LinkedList<Tuple<K, V>>();}public V Get(K key){if (!dict.ContainsKey(key)){return default(V);}var node = dict[key];linkedList.Remove(node);linkedList.AddLast(node);return node.Value.Item2;}public void Put(K key, V value){if (dict.ContainsKey(key)){var node = dict[key];linkedList.Remove(node);}var newNode = new LinkedListNode<Tuple<K, V>>(Tuple.Create(key, value));dict[key] = newNode;linkedList.AddLast(newNode);if (dict.Count > capacity){var firstNode = linkedList.First;linkedList.RemoveFirst();dict.Remove(firstNode.Value.Item1);}}
}// Usage:
var lruCache = new LRUCache<string, int>(2);
lruCache.Put("a", 1);
lruCache.Put("b", 2);
Console.WriteLine(lruCache.Get("a")); // Output: 1
lruCache.Put("c", 3);
Console.WriteLine(lruCache.Get("b")); // Output: 0 (not found)

分析

使用双向链表(双向链表节点具有指向前一个节点和后一个节点的指针)可以实现 O(1)时间删节点。在删除节点时,我们只需要更新它前一个节点的指针和后一个节点的指针,就可以把这个节点从链表中删除。

代码实现二:OrderedDictionary

using System.Collections.Specialized;namespace Tools
{public class LRUCache<K, V>{private OrderedDictionary dict;private int capacity;public LRUCache(int capacity){this.capacity = capacity;dict = new OrderedDictionary();}public V Pop(K key){if (!dict.Contains(key)){return default(V);}var value = (V)dict[key];dict.Remove(key);dict.Add(key, value);return value;}public void Push(K key, V value){if (dict.Contains(key)){dict.Remove(key);}else if (dict.Count >= capacity){dict.RemoveAt(0);}dict.Add(key, value);}}
}

分析

OrderedDictionary 是一个 C# 内置的数据结构,它是一个有序的键值对集合,支持按顺序获取和遍历键值对。
比较上一种实现方式的优点是:代码简洁,只使用一个数据结构。缺点是运行效率会慢。

OrderedDictionary与Dictionary类似,但是它具有以下不同之处:

  • OrderedDictionary内部维护了一个按添加顺序排序的键列表。
  • OrderedDictionary在内部使用了两个ArrayList,一个用于存储键,另一个用于存储与键相关联的值。这意味着OrderedDictionary的效率不如Dictionary高,因为每次检索或添加键值对时都需要额外的操作。

项目案例

在 Unity 开发中,我们很常用到对象池,所以我们可以使用 LRU 来对对象池进行优化,避免过多的内存占用。

预告

下一篇文章我们就来实战,实现一个 LRU 对象池。

结尾

之前写过一篇关于对象池的文章,现在来看写的并不是很好,所以来考虑优化下。
Unity学习笔记–如何优雅简便地利用对象池生成游戏对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/30212.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React中使用mobx管理状态数据使用样例

MobX 是一个身经百战的库&#xff0c;它通过运用透明的函数式响应编程&#xff08;Transparent Functional Reactive Programming&#xff0c;TFRP&#xff09;使状态管理变得简单和可扩展。官网地址&#xff1a;关于 MobX | MobX中文文档 | MobX中文网 安装依赖 mobx-react-…

QT的信号槽的四种写法和五种链接方式

目录 四种信号槽写法&#xff1a; 五种连接方式&#xff1a; 实例&#xff1a; 常见错误及改正&#xff1a; 错误1: 未连接信号与槽 错误2: 信号和槽参数不匹配 错误3: 未使用Q_OBJECT宏 错误4: 跨线程连接未处理 在Qt中&#xff0c;信号&#xff08;Signal&#xff09…

openEuler-OECA考试报名火热开启,尊享半价优惠 作者:HopeInfra 发布时间:2023-08-10

近日&#xff0c;润和软件人才评定报名系统已成功上线运行&#xff0c;现openEuler-OECA人才评定考试报名优惠活动火热开启&#xff0c;欢迎大家报名咨询&#xff01; 关于openEuler人才评定 随着openEuler及其发行版本在各个行业使用量逐年增多&#xff0c;相关人才的评定诉求…

企业内业务系统与Activiti流程引擎的结合(十)

书接上回 Activiti流程接口中台 接口实现 一、任务指派(委托) /task/instance/{taskId}/reassign 查询 activiti 相关表 本方法使用的全部是 activiti 自带的API 1. 请求参数 {"assigneeId": "000001", "tenantId": "abcd" } …

突破笔试:力扣129. 求根节点到叶节点数字之和

1. 题目链接&#xff1a;129. 求根节点到叶节点数字之和 给你一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。每条从根节点到叶节点的路径都代表一个数字&#xff1a;例如&#xff0c;从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 …

http相关知识点

文章目录 长链接http周边会话保持方案1方案2 基本工具postmanFiddlerFiddler的原理 长链接 一张网页实际上可能会有多种元素组成&#xff0c;这也就说明了网页需要多次的http请求。可由于http是基于TCP的&#xff0c;而TCP创建链接是有代价的&#xff0c;因此频繁的创建链接会…

理解 with torch.no_grad():

在看深度学习预测推理的代码时&#xff0c;经常会看到下面这行代码 with torch.no_grad&#xff08;&#xff09;&#xff1a;年少无知的我不知道是什么意思。今天问了一下GPT&#xff0c;给出的答案是这样的&#xff1a; 在 PyTorch 中&#xff0c;torch.no_grad() 是一个上…

大数据Flink(五十六):Standalone伪分布环境(开发测试)

文章目录 Standalone伪分布环境(开发测试) 一、架构图 二、环境准备 三、下载安装包</

flutter遇到的小问题记录

flutter-getx的Get.bottomSheet组件改变高度 Get.bottomSheet( isScrollControlled: true,) isScrollControlled: true 就是控制高度 (无语) 截取视频第一针 返回的是本地url 或者Uint8List的数据 String? videoStr await VideoThumbnail.thumbnailFile(video: videoPath,…

微信小程序 map地图(轨迹)

allMarkers效果图 废话少说直接上马&#xff08;最后是我遇到的问题&#xff09; cover-view是气泡弹窗&#xff0c;可以自定义弹窗&#xff0c;要配合js&#xff1a;customCallout&#xff0c;如果是非自定义的话&#xff1a;callout&#xff08;可以修改颜色、边框宽度、圆角…

java输出GB2312、GBK、GB18030、UTF-8所有的字符

相关文章 【转】彻底搞明白 GB2312、GBK 、GB18030和UTF-8 1.ASICII、GB2312、GBK、GB18030 以及 UTF8 的关系 2.编写代码 引入依赖&#xff1a;hutool工具类 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId>&…

轻松批量自定义重命名,为文件夹加上个性化编号!

在日常生活和工作中&#xff0c;我们经常需要对大量的文件夹进行重命名&#xff0c;以更好地管理和整理文件。然而&#xff0c;手动逐个修改文件夹名称费时费力&#xff0c;效率低下。现在&#xff0c;我们为您推荐一款简单易用的工具&#xff0c;可以帮助您快速批量自定义重命…

LoRaWAN网关与网络服务器(NS)的通信CUPS 协议介绍

LoRa Basics™ Station 定期查询 CUPS 服务器以获取更新。该协议是 HTTP/REST,使用Credentials中描述的客户端/服务器身份验证方法。对于每个查询,工作站都会提供有关其当前状态的信息,并接收包含其 LNS 和 CUPS 凭证更新的二进制 blob,以及具有任意更新的通用数据段。 通…

网络安全的相关知识点

网络安全威胁类型&#xff1a; 1.窃听&#xff1a;广播式网络系统。 2.假冒 3.重放&#xff1a;重复一份报文或者报文的一部分&#xff0c;以便产生一个被授权的效果。 4.流量分析 5.数据完整性破坏 6.拒绝服务 7.资源的非授权使用 8.陷门和特洛伊木马&#xff1a;木马病毒有客…

Java课题笔记~ Spring 的事务管理

一、Spring 的事务管理 事务原本是数据库中的概念&#xff0c;在 Dao 层。但一般情况下&#xff0c;需要将事务提升到业务层&#xff0c;即 Service 层。这样做是为了能够使用事务的特性来管理具体的业务。 在 Spring 中通常可以通过以下两种方式来实现对事务的管理&#xff…

Vue3大屏幕动态滚动

Vue3 大屏数字滚动效果 随着大屏幕技术的发展&#xff0c;大屏数字滚动效果在各种应用场景中越来越常见&#xff0c;例如数字展示、统计数据展示等。Vue3 作为一种流行的前端开发框架&#xff0c;提供了强大的工具和便捷的开发方式&#xff0c;非常适合实现大屏数字滚动效果。…

花样滑冰选手骨骼点动作识别

2023 CCF BDCI 基于飞桨实现花样滑冰选手骨骼点动作识别 16名方案以及总结 比赛任务 花样滑冰与其他运动项目相比&#xff0c;其动作类型的区分难度更大&#xff0c;这对识别任务来说是极大的挑战。对于花样滑冰动作识别任务&#xff0c;主要难点如下&#xff1a; (1) 花样滑…

Python-OpenCV中的图像处理-图像梯度

Python-OpenCV中的图像处理-图像梯度 图像梯度Sobel 算子和 Scharr 算子Laplacian 算子 图像梯度 图像梯度&#xff0c;图像边界等使用到的函数有&#xff1a; cv2.Sobel()&#xff0c; cv2.Scharr()&#xff0c; cv2.Laplacian() 等原理&#xff1a;梯度简单来说就是求导。Op…

fastadmin、vue、react图标库适用于多种框架

在二开fastadmin中&#xff0c;在写vue以及react时&#xff0c;侧边导航栏以及按钮中常常需要很多图标&#xff0c;那么这些图标应该去哪里得到呢&#xff0c;在这里给大家一个链接&#xff0c;这里有丰富的图标库&#xff0c;可以找到自己想要的进行使用。 点击下方链接&…

gstreamer-pipeline用法汇总

生成mp4 生成2s包含video和audio的mp4 gst-launch-1.0 -e --gst-debug2 \ \ videotestsrc num-buffers60 ! video/x-raw,framerate30/1 ! \ openh264enc ! h264parse ! muxer.video_0 \ \ audiotestsrc num-buffers90 ! audio/x-raw,channels1 ! \ fdkaacenc ! aacparse ! mu…