当前位置: 首页 > news >正文

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 核心思想代码实现一&#xff1a;双向链表 哈希表分析代码实现二&#xff1a;OrderedDictionary分析项目案例预告结尾 什么是 LRU 在计算机系统中&#xff0c;LRU&#xff08;Least Recently Used&#xff0c;最近最少使用&#xff09;是一种缓存置换算法。…...

【一】初步认识数据库

数据库概览数据库 缘起表(Table)的理解用表来定义数据库数据库系统的理解概念层次的理解实例层次的理解 数据库管理系统的理解从用户角度看从系统实现角度看典型的数据库管理系统 数据库语言数据库定义、操纵、控制语言数据库语言 VS 高级语言 内容回顾练习 数据库概览 走马观…...

HTML <section> 标签

实例 文档中的区段&#xff0c;解释了 PRC&#xff1a; <section><h1>PRC</h1><p>The Peoples Republic of China was born in 1949...</p> </section>定义和用法 <section> 标签定义文档中的节&#xff08;section、区段&#x…...

PHP 之房贷计算器、组合贷

一、等额本金 // &#xff08;等额本金&#xff09; //$loanAmount>贷款金额 //$loanPeriod>贷款年限 //$interestRate>贷款利息 function calculateEqualPrincipalPayment($loanAmount, $loanPeriod, $interestRate) {$monthlyPrincipal $loanAmount / ($loanPerio…...

解决Vue+Element UI使用表单rules国际化时From表单验证信息不能实时更新

说明&#xff1a;该篇博客是博主一字一码编写的&#xff0c;实属不易&#xff0c;请尊重原创&#xff0c;谢谢大家&#xff01; 博主在工作之余开始进行自动化测试平台的开发&#xff0c;虽然已经996一个月了但是还是在使劲挤时间做这件事情&#xff0c;目前平台使用前端框架vu…...

友善之臂NanoPi NEO利用fbtft驱动点亮1.69寸ST7789V2屏幕

屏幕介绍 本文以中景园1.69寸LCD&#xff0c;驱动芯片ST7789V2该款屏幕示例&#xff0c;屏幕的分辨率为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

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

Games101学习笔记2

参考博客&#xff1a;GAMES101 梳理 / 个人向图形学笔记_games101笔记_river_of_sebajun的博客-CSDN博客 lecture 05 Rasterization 1(Triangles) 光栅化 把东西画在屏幕上的过程就是光栅化的过程 视口变换 为什么模型用三角形&#xff1f; 最基本的几何平面&#xff1b;保…...

java字符串String类的常用方法

java字符串String类的常用方法 字符串的创建&#xff1a; (1)定义字符串直接赋值&#xff0c;在字符串池中开辟空间() String str1“Hello”;//在字符串池中写入字符串"hello" String str2“Hello”;//直接引用字符串池中的"Hello" System.out.println(s…...

自动化测试如何解决chrome自动更新问题

问题 调试好的自动化测试脚本&#xff0c;有时候总是在第一天或过几天就不好使了。产品并未进行功能逻辑&#xff0c;ui修改&#xff0c;一切还和调试自动化脚本的时候保持一致。运行自动化测试脚本时&#xff0c;控制台总是会在driver webdriver.Chrome()这一行报错。 问题…...

闲鱼卖货:新手容易踩坑的7个地方。赶紧看看有没有中招?

科思创业汇 大家好&#xff0c;这里是科思创业汇&#xff0c;一个轻资产创业孵化平台。赚钱的方式有很多种&#xff0c;我希望在科思创业汇能够给你带来最快乐的那一种&#xff01; 这是我以前的一个学生收到的第一个非法通知。他告诉我&#xff0c;他当时很害怕&#xff0c;…...

PowerShell 获取某目录下所有的文件、文件夹,同时对获取到的文件路径字符串进行替换处理

PowerShell 获取某目录下所有的文件、文件夹&#xff0c;同时对获取到的文件路径字符串进行替换处理 前言&#xff1a; 为了将Windows系统下的Java编译文件与linux服务器上的文件进行比较&#xff0c;故进行此文件路径的获取及路径处理。 在只有文件路径 而没有实际文件的情况下…...

JUC并发编程之线程锁(一)

目录 1.ReentrantLock(互斥锁) 2.ReentRantReaderWriterLock&#xff08;互斥读写锁&#xff09; 3.StampedLock&#xff08;无障碍锁&#xff09; 4.Condition&#xff08;自定义锁&#xff09; 5.LockSupport 问题引出&#xff1a; 由于传统的线程控制需要用到同步机制Sy…...

Android AlertDialog标题居中

网上很多做法都是使用setCustomTitle方法实现的&#xff0c;我偏不&#xff0c;因为我已经找到了标题的textView了&#xff1a; 在show了之后可以拿到标题&#xff08;注意一定是show之后才能拿得到&#xff0c;create之后拿也是空的&#xff09;&#xff1a; TextView title…...

k8s界面化平台dashboard、kubesphere、Rancher对比

k8s集群管理dashboard有很多&#xff0c;比如kuboard、官方发dashboard、kubesphere、Rancher等等。 Dashboard、KubeSphere 和 Rancher 都是流行的 Kubernetes 管理和操作界面。它们都提供了图形化的用户界面&#xff0c;以简化对 Kubernetes 集群的管理和监控。每个工具都有其…...

【字符串左旋】

字符串左旋 1.题目要求 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 例如&#xff1a; ABCD左旋一个字符得到BCDA ABCD左旋两个字符得到CDAB 2.解法&#xff1a; 设计循环使其可以旋1次&#xff0c;然后让他执行n次是一个最简单的思路&#xff1a; 函数实现&#xf…...

Docker Dirtypipe(CVE-2022-0847)漏洞复现与分析容器逃逸

安装环境 ./metarget cnv install cve-2022-0847 --verbose 原理 同脏牛&#xff0c;通过写只读内存&#xff0c;对映射的内存做篡改 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 实现的接口自动化框架。 前言 公司突然要求你做自动化&#xff0c;但是没有代码基础不知道怎么做&#xff1f;或者有自动化…...

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…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

给网站添加live2d看板娘

给网站添加live2d看板娘 参考文献&#xff1a; stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下&#xff0c;文章也主…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

ZYNQ学习记录FPGA(一)ZYNQ简介

一、知识准备 1.一些术语,缩写和概念&#xff1a; 1&#xff09;ZYNQ全称&#xff1a;ZYNQ7000 All Pgrammable SoC 2&#xff09;SoC:system on chips(片上系统)&#xff0c;对比集成电路的SoB&#xff08;system on board&#xff09; 3&#xff09;ARM&#xff1a;处理器…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...