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学习笔记–如何优雅简便地利用对象池生成游戏对象
相关文章:
Unity学习笔记--使用 C# 开发一个 LRU
目录 什么是 LRULRU 核心思想代码实现一:双向链表 哈希表分析代码实现二:OrderedDictionary分析项目案例预告结尾 什么是 LRU 在计算机系统中,LRU(Least Recently Used,最近最少使用)是一种缓存置换算法。…...

【一】初步认识数据库
数据库概览数据库 缘起表(Table)的理解用表来定义数据库数据库系统的理解概念层次的理解实例层次的理解 数据库管理系统的理解从用户角度看从系统实现角度看典型的数据库管理系统 数据库语言数据库定义、操纵、控制语言数据库语言 VS 高级语言 内容回顾练习 数据库概览 走马观…...
HTML <section> 标签
实例 文档中的区段,解释了 PRC: <section><h1>PRC</h1><p>The Peoples Republic of China was born in 1949...</p> </section>定义和用法 <section> 标签定义文档中的节(section、区段&#x…...

PHP 之房贷计算器、组合贷
一、等额本金 // (等额本金) //$loanAmount>贷款金额 //$loanPeriod>贷款年限 //$interestRate>贷款利息 function calculateEqualPrincipalPayment($loanAmount, $loanPeriod, $interestRate) {$monthlyPrincipal $loanAmount / ($loanPerio…...

解决Vue+Element UI使用表单rules国际化时From表单验证信息不能实时更新
说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 博主在工作之余开始进行自动化测试平台的开发,虽然已经996一个月了但是还是在使劲挤时间做这件事情,目前平台使用前端框架vu…...

友善之臂NanoPi NEO利用fbtft驱动点亮1.69寸ST7789V2屏幕
屏幕介绍 本文以中景园1.69寸LCD,驱动芯片ST7789V2该款屏幕示例,屏幕的分辨率为240*280 屏幕引脚说明 NanoPi NEO IO介绍 屏幕与板子的IO连接关系 屏幕NanoPi NEOGNDGNDVCC3.3VSCLPC2SDAPC0RESPG11DCPA1CSPC3BLKPA0 下载交叉编译器和linux内核源码并按教…...

MFC第三十天 通过CToolBar类开发文字工具栏和工具箱、GDI+边框填充以及基本图形的绘制方法、图形绘制过程的反色线模型和实色模型
文章目录 CControlBar通过CToolBar类开发文字工具栏和工具箱CMainFrame.hCAppCMainFrm.cppCMainView.hCMainView.cppCEllipse.hCEllipse.cppCLine.hCLine.cppCRRect .hCRRect .cpp CControlBar class AFX_NOVTABLE CControlBar : public CWnd{DECLARE_DYNAMIC(CControlBar)pro…...

Android Https
本质:在客户端和服务端使用非对称加密协商出一套对称密钥,每次发送数据前加密,收到后解密,达到加密传输 http ssl 在http之下增加了安全层,用于保障http的加密传输 HTTPS连接 TLS连接步骤 1.客户端发送 client h…...

Games101学习笔记2
参考博客:GAMES101 梳理 / 个人向图形学笔记_games101笔记_river_of_sebajun的博客-CSDN博客 lecture 05 Rasterization 1(Triangles) 光栅化 把东西画在屏幕上的过程就是光栅化的过程 视口变换 为什么模型用三角形? 最基本的几何平面;保…...
java字符串String类的常用方法
java字符串String类的常用方法 字符串的创建: (1)定义字符串直接赋值,在字符串池中开辟空间() String str1“Hello”;//在字符串池中写入字符串"hello" String str2“Hello”;//直接引用字符串池中的"Hello" System.out.println(s…...
自动化测试如何解决chrome自动更新问题
问题 调试好的自动化测试脚本,有时候总是在第一天或过几天就不好使了。产品并未进行功能逻辑,ui修改,一切还和调试自动化脚本的时候保持一致。运行自动化测试脚本时,控制台总是会在driver webdriver.Chrome()这一行报错。 问题…...

闲鱼卖货:新手容易踩坑的7个地方。赶紧看看有没有中招?
科思创业汇 大家好,这里是科思创业汇,一个轻资产创业孵化平台。赚钱的方式有很多种,我希望在科思创业汇能够给你带来最快乐的那一种! 这是我以前的一个学生收到的第一个非法通知。他告诉我,他当时很害怕,…...
PowerShell 获取某目录下所有的文件、文件夹,同时对获取到的文件路径字符串进行替换处理
PowerShell 获取某目录下所有的文件、文件夹,同时对获取到的文件路径字符串进行替换处理 前言: 为了将Windows系统下的Java编译文件与linux服务器上的文件进行比较,故进行此文件路径的获取及路径处理。 在只有文件路径 而没有实际文件的情况下…...

JUC并发编程之线程锁(一)
目录 1.ReentrantLock(互斥锁) 2.ReentRantReaderWriterLock(互斥读写锁) 3.StampedLock(无障碍锁) 4.Condition(自定义锁) 5.LockSupport 问题引出: 由于传统的线程控制需要用到同步机制Sy…...
Android AlertDialog标题居中
网上很多做法都是使用setCustomTitle方法实现的,我偏不,因为我已经找到了标题的textView了: 在show了之后可以拿到标题(注意一定是show之后才能拿得到,create之后拿也是空的): TextView title…...
k8s界面化平台dashboard、kubesphere、Rancher对比
k8s集群管理dashboard有很多,比如kuboard、官方发dashboard、kubesphere、Rancher等等。 Dashboard、KubeSphere 和 Rancher 都是流行的 Kubernetes 管理和操作界面。它们都提供了图形化的用户界面,以简化对 Kubernetes 集群的管理和监控。每个工具都有其…...
【字符串左旋】
字符串左旋 1.题目要求 实现一个函数,可以左旋字符串中的k个字符。 例如: ABCD左旋一个字符得到BCDA ABCD左旋两个字符得到CDAB 2.解法: 设计循环使其可以旋1次,然后让他执行n次是一个最简单的思路: 函数实现…...
Docker Dirtypipe(CVE-2022-0847)漏洞复现与分析容器逃逸
安装环境 ./metarget cnv install cve-2022-0847 --verbose 原理 同脏牛,通过写只读内存,对映射的内存做篡改 EXP docker run --rm -it -v $(pwd):/exp --cap-addCAP_DAC_READ_SEARCH ubuntu如果提示 Unknown capability to add: "CAP_CAP_DAC_RE…...

python接口自动化测试框架2.0,让你像Postman一样编写测试用例,支持多环境切换、多业务依赖、数据库断言等
项目介绍 接口自动化测试项目2.0 软件架构 本框架主要是基于 Python unittest ddt HTMLTestRunner log excel mysql 企业微信通知 Jenkins 实现的接口自动化框架。 前言 公司突然要求你做自动化,但是没有代码基础不知道怎么做?或者有自动化…...

Vue.js2+Cesium1.103.0 九、淹没分析效果
Vue.js2Cesium1.103.0 九、淹没分析效果 Demo <template><divid"cesium-container"style"width: 100%; height: 100%;"><spanid"button"style"position: absolute; right: 50px; top: 50px; z-index: 999; font-size: 24px…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...