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

这篇具有很好参考价值的文章主要介绍了Unity学习笔记--使用 C# 开发一个 LRU。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是 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学习笔记–如何优雅简便地利用对象池生成游戏对象文章来源地址https://www.toymoban.com/news/detail-637044.html

到了这里,关于Unity学习笔记--使用 C# 开发一个 LRU的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • WinFrom、C# 学习记录五 开发一个鼠标自动点击小软件

            经常会被问到需要点击软件的,主要都是玩游戏的盆友,但是也有其它用途的。所以简单弄了一个,打算每当有时间,有需求,就加一些小功能。         这里主要是要记录一下相关开发工作,也记录一些使用/更新的信息。         【2022/08/22】版本v1.0(初始版

    2024年02月16日
    浏览(34)
  • 【HoloLens2】【Unity】【MRTK】开发笔记(一):创建第一个项目

    前言 标题这三者的关系是:假如这里有一个电子厂,Unity是机床,MRTK是零件和螺丝刀,HoloLens2是超市货架。最后在机床上生产出的商品要摆到货架上售卖。机床官方建议用Unity,但Unreal也是很不错的选择,只是部分微软云服务暂时还不支持。 本电子厂女工将从零开始生产一个

    2024年02月10日
    浏览(32)
  • Unity3D高级编程主程手记 学习笔记二:C#技术要点

    1.Untiy3D中C#的底层原理 Unity底层在运行C#程序时有两种机制:一种是Mono,另一种是IL2CPP。 Mono存在的目的是为了跨平台 ,因为最初C#只支持Windows。而IL可以看成是一种汇编语言且完全基于堆栈,必须运行在虚拟机上。也就是说C#会被编译器编译成IL,当需要他们时就会被实时的

    2024年02月08日
    浏览(43)
  • C#从零开始的学习笔记(2)运行和开发环境

    .NET Framework C#的运行环境,换句话说就是.NET Framework的运行环境。Windows7中包含了.NET Framework3.5,windows10中包含了.NET Framework4.6,Windows10 v1703中包含了.NET Framework4.7。安装visual studio的时候,也会安装相应版本的.NET Framework。当然,各位读者也可以自行前往Microsoft官网上下载最新的

    2024年02月08日
    浏览(38)
  • 【Unity】Unity开发学习和项目实践02——创建第一个Unity项目和游戏物体

    创建第1个Unity项目 打开Unity hub,点击新项目 以下有四处地方需要注意选择: 1.Unity编辑器版本 2.项目模板 3.项目名称 4.项目保存位置 点击创建项目 ok,进入编辑器了 把编辑器界面布局稍微改一下,改成2by3 点击Edit 点击 project settings,这是对我们所创建工程的设置 此外还有对

    2024年01月25日
    浏览(35)
  • Unity学习笔记 - 第一个Hello World都算不上的项目

            这里不细说安装了,首先需要Visual Studio,然后要安装Unity Hub,Unity Hub就像一个管理平台,安装完它之后,可以在它的界面上选择安装各个版本的编辑器。 开始您的创意项目并下载 Unity Hub | Unity 通过 3 个简单的步骤下载 Unity,开始使用世界上颇受欢迎的开发平台,

    2024年04月12日
    浏览(29)
  • 初学unity开发学习笔记----第一天

    以下是学习unity知识的心得,类似备忘录,肯定是存在有漏洞的地方或者专业名词使用不恰当的地方。。。 目标:编写小球wasd移动的效果 1.下载unity hub和unity引擎: (1).前往官网:Unity实时内容开发平台 -实时3D引擎、2D、VRAR可视化数据 | Unity中国官网 (2).选择unity选项卡,选择下载

    2024年02月09日
    浏览(32)
  • Unity使用c#开发遇上的问题(一)(c#中无法引入input,双击unity中的c#文件无反应,unity中刚体设置后仍然穿越问题)

    闲着无聊,想用unity编一编小游戏,遇上的坑(一) 我使用的是vs2019,unity版本是2022.1,下载器Hub。 在asset中创建c#脚本移动cube。在写入X,Y偏移量时没有unity引擎的Input函数。 解决方法: 1.首选项中设置中文语言。

    2024年02月07日
    浏览(37)
  • C# 学习笔记--个人学习使用 <2>

    什么是委托? 委托 Delegate 是函数指针的升级版 Delegate 的意思是,这有一件事情,我不亲自去做,而是交给别人去做,也就是间接地去做; 我们可以看到输出结果如下: 在这个例子里,是通过函数的名字,来调用,是直接调用 我们可以看到输出结果如下: 可以看到输出结果

    2024年02月11日
    浏览(32)
  • 【设计并实现一个满足 LRU (最近最少使用) 缓存约束的数据结构】

    LRU是Least Recently Used的缩写,意为最近最少使用。它是一种缓存淘汰策略,用于在缓存满时确定要被替换的数据块。LRU算法认为,最近被访问的数据在将来被访问的概率更高,因此它会优先淘汰最近最少被使用的数据块,以给新的数据块腾出空间。 如图所示: 先来3个元素进入

    2024年01月24日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包