lua-lru缓存算法解析
lua-lru缓存算法解析
- 主要功能和作用
- 1. 缓存管理:
- 2. 数据存储与访问:
- 3. 迭代器:
- 4. 容量管理:
- 具体实现细节
- 使用场景
- 使用示例
lua-lru 是 Lua 语言中的一个 LRU(Least Recently Used,最近最少使用)缓存实现,是一个基于哈希表和双向链表的数据结构,用于管理缓存中的数据项,并根据访问频率自动淘汰最不常用的数据项
-- lua-lru, LRU cache in Lua
-- Copyright (c) 2015 Boris Nagaev
-- See the LICENSE file for terms of use.local lru = {}function lru.new(max_size, max_bytes)assert(max_size >= 1, "max_size must be >= 1")assert(not max_bytes or max_bytes >= 1,"max_bytes must be >= 1")-- current sizelocal size = 0local bytes_used = 0-- map is a hash map from keys to tuples-- tuple: value, prev, next, key-- prev and next are pointers to tupleslocal map = {}-- indices of tuplelocal VALUE = 1local PREV = 2local NEXT = 3local KEY = 4local BYTES = 5-- newest and oldest are ends of double-linked listlocal newest = nil -- firstlocal oldest = nil -- lastlocal removed_tuple -- created in del(), removed in set()-- remove a tuple from linked listlocal function cut(tuple)local tuple_prev = tuple[PREV]local tuple_next = tuple[NEXT]tuple[PREV] = niltuple[NEXT] = nilif tuple_prev and tuple_next thentuple_prev[NEXT] = tuple_nexttuple_next[PREV] = tuple_prevelseif tuple_prev then-- tuple is the oldest elementtuple_prev[NEXT] = niloldest = tuple_prevelseif tuple_next then-- tuple is the newest elementtuple_next[PREV] = nilnewest = tuple_nextelse-- tuple is the only elementnewest = niloldest = nilendend-- insert a tuple to the newest endlocal function setNewest(tuple)if not newest thennewest = tupleoldest = tupleelsetuple[NEXT] = newestnewest[PREV] = tuplenewest = tupleendendlocal function del(key, tuple)map[key] = nilcut(tuple)size = size - 1bytes_used = bytes_used - (tuple[BYTES] or 0)removed_tuple = tupleend-- removes elemenets to provide enough memory-- returns last removed element or nillocal function makeFreeSpace(bytes)while size + 1 > max_size or(max_bytes and bytes_used + bytes > max_bytes)doassert(oldest, "not enough storage for cache")del(oldest[KEY], oldest)endendlocal function get(_, key)local tuple = map[key]if not tuple thenreturn nilendcut(tuple)setNewest(tuple)return tuple[VALUE]endlocal function set(_, key, value, bytes)local tuple = map[key]if tuple thendel(key, tuple)endif value ~= nil then-- the value is not removedbytes = max_bytes and (bytes or #value) or 0makeFreeSpace(bytes)local tuple1 = removed_tuple or {}map[key] = tuple1tuple1[VALUE] = valuetuple1[KEY] = keytuple1[BYTES] = max_bytes and bytessize = size + 1bytes_used = bytes_used + bytessetNewest(tuple1)elseassert(key ~= nil, "Key may not be nil")endremoved_tuple = nilendlocal function delete(_, key)return set(_, key, nil)endlocal function mynext(_, prev_key)local tupleif prev_key thentuple = map[prev_key][NEXT]elsetuple = newestendif tuple thenreturn tuple[KEY], tuple[VALUE]elsereturn nilendend-- returns iterator for keys and valueslocal function lru_pairs()return mynext, nil, nilendlocal mt = {__index = {get = get,set = set,delete = delete,pairs = lru_pairs,},__pairs = lru_pairs,}return setmetatable({}, mt)
endreturn lru
主要功能和作用
1. 缓存管理:
- lua-lru 可创建一个最多可以存储 max_size 个数据项的缓存,并且可以选择限制缓存的总字节数 max_bytes
- 当缓存达到最大容量时,会自动淘汰最久未使用的数据项,以腾出空间给新数据
2. 数据存储与访问:
- set(key, value, bytes):将数据项存储到缓存中,如果缓存中已经存在相同的 key,则会替换旧数据,如果缓存达到最大容量或字节限制,会自动淘汰最久未使用的数据项
- get(key):从缓存中获取数据项,如果数据项存在,将其移动到链表的最新位置(即标记为最近使用)
- delete(key):从缓存中删除指定的数据项
3. 迭代器:
- lru_pairs():返回一个迭代器,用于遍历缓存中的所有数据项,迭代器按最近使用到最久未使用的顺序遍历
4. 容量管理:
- makeFreeSpace(bytes):当缓存即将超出容量限制时,自动删除最久未使用的数据项,直到有足够的空间或字节数
具体实现细节
- 双向链表:用于维护数据项的访问顺序,最近访问的数据项放在链表的前端,最久未访问的数据项放在链表的后端
- 哈希表:用于快速查找数据项,哈希表的键是缓存的键,值是一个包含数据、链表前后指针等信息的数据结构
- 自动淘汰:当缓存达到最大容量或字节数限制时,通过删除链表尾部的数据项来释放空间
使用场景
- 数据缓存:适用于需要缓存数据的场景,特别是在数据访问频率高但存储空间有限的情况下
- 限流:可以用于实现限流机制,淘汰掉长时间未使用的数据项,确保缓存中保留的是最近活跃的数据
- 性能优化:在一些需要频繁访问数据但数据量较大的场景中,通过 LRU 缓存可以显著提高访问性能
使用示例
local lru = require("lru")local cache = lru.new(3, 100) -- 创建一个最多存储3个数据项,最大100字节的缓存cache:set("key1", "value1", 10) -- 存储数据项,占用10字节
cache:set("key2", "value2", 20) -- 存储数据项,占用20字节
cache:set("key3", "value3", 30) -- 存储数据项,占用30字节print(cache:get("key1")) -- 输出 "value1"cache:set("key4", "value4", 40) -- 存储新数据项,占用40字节,淘汰 "key1" 因为它是最近最少使用的print(cache:get("key1")) -- 输出 nil,因为 "key1" 已经被淘汰for key, value in cache:pairs() doprint(key, value) -- 按最近使用到最久未使用的顺序遍历缓存
end
相关文章:
lua-lru缓存算法解析
lua-lru缓存算法解析 主要功能和作用1. 缓存管理:2. 数据存储与访问:3. 迭代器:4. 容量管理: 具体实现细节使用场景使用示例 lua-lru 是 Lua 语言中的一个 LRU(Least Recently Used,最近最少使用࿰…...
Python - 初识Python;Python解释器下载安装;Python IDE(一)
一、初识Python Python 是一种高级编程语言,Python是一种面向对象的解释型计算机程序设计语言,Python由荷兰国家数学与计算机科学研究中心的吉多范罗苏姆()Guido van Rossum吉多范罗苏姆()于1989 年底发明…...
鸿蒙学习基本概念
文章目录 1、当前移动应用开发中遇到的主要挑战包括:2、 新的应用生态应该具备如下特征:3、HarmonyOS 应用:使用 HarmonyOS SDK 开发的应用程序,能够在华为终端设备4、HarmonyOS 元服务:元服务是 HarmonyOS 面向万物互…...
正则表达式(补充)
定义一个正则表达式 const 变量名 /表达式/ const reg /前端/ 匹配看字符串中有无前端俩字 正则对象上的一些方法 test() 用于查看正则表达式与指定的字符串是否匹配 const reg /前端/ const res reg.test(学前端,找黑马) //匹配到返回true,匹配不到返回fa…...
第23课-C++-红黑树的插入与旋转
🌇前言 红黑树是一种自平衡的二叉搜索树,因其出色的性能,广泛应用于实际中。Linux 内核中的 CFS 调度器便是一个使用红黑树的例子,这足以说明它的重要性。红黑树的实现通过红黑两种颜色的控制来维持平衡,并在必要时使…...
【C#】C#编程入门指南:构建你的.NET开发基础
文章目录 前言:1. C# 开发环境 VS的基本熟悉2. 解决方案与项目的关系3. 编辑、编译、链接、运行4. 托管代码和CLR4.1 CLR:4.2 C# 代码第编译过程(两次编译的) 5. 命名空间6. 类的组成与分析7. C# 的数据类型7.1 值类型7.2 引用类型…...
[系统安全] PE文件知识在免杀中的应用
0x1 PE文件与免杀思路 基于PE文件结构知识的免杀技术主要用于对抗启发式扫描。 通过修改PE文件中的一些关键点来达到欺骗反病毒软件的目的。 修改区段名 1.1 移动PE文件头位置免杀 工具:PeClean SizeOfOptionalHeader字段来描述扩展头的大小,恒定值为…...
相机标定原理
相机标定原理 什么是相机标定相机畸变 什么是相机标定 为了确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,需建立相机成像的几何模型,几何模型参数即为相机参数,求解相机参数的过程就是相机标定。 坐标系 **世界坐标…...
Linux基础开发工具使用
目录 1. 软件包管理器yum 1.1 概念介绍 1.2 更换镜像源(可选) 1.3 工具的搜索/查看/安装/卸载 1.4 优势 2. vim编辑器 2.1 vi和vim 2.2 三种常用模式和操作 2.3 配置vim 3. Linux编译器-gcc/g 4. Linux调试器-gdb 5. make和Makefile 6.…...
蓝牙PBAP协议及Android实现
文章目录 前言一、什么是PBAP协议?PBAP的关键功能 二、PBAP的工作流程PBAP流程 三、PBAP在Android实现关键步骤:1. 检查设备是否支持 PBAP 服务 2. 创建 PBAP 连接3. 发送 OBEX 请求4. 解析 vCard 数据数据存储与展示6. 性能优化建议7. 完整示例…...
Py之pymupdf:基于langchain框架结合pymupdf库实现输出每个PDF页面的文本内容、元数据等
Py之pymupdf:基于langchain框架结合pymupdf库实现输出每个PDF页面的文本内容、元数据等 目录 PyMuPDFLoader类 初始化 属性 方法 __init__(file_path, *, headers=None, extract_images=False, **kwargs) lazy_load() aload() alazy_load() load(**kwargs) load_and…...
LeetCode题解:17.电话号码的数字组合【Python题解超详细,回溯法、多叉树】,知识拓展:深度优先搜索与广度优先搜索
题目描述 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 示例 1: 输入:digits "23" 输出…...
《JVM第10课》内存溢出(OOM)排查过程
文章目录 常用命令1. jps2. jconsole3. jstat4. jmap 工具1.jvisualvm 排查OOM的方法其实很简单很简单。 如果能找到拋OOM的日志,可以在日志里看到是哪一行抛出的OOM异常。如果找不到日志,那么处理方式是导出Java进程的内存快照,然后用工具查…...
Thinkphp6视图介绍
一.MVC MVC 软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller) ThinkPHP6 是一个典型的 MVC 架构 控制器—控制器,用于将用户请求转发给相应的Model进行处理&a…...
躺平成长-人工智能进行编程-(12)
躺平成长: 让每一个人在科技(开源的网络/智能科技对于生活琐事的处理)的帮助下,实现养生反卷,躺平成长。 开源竞争: 当你无法彻底掌握技术的时候,你就开源这个技术,形成技术依赖&a…...
计算机网络中的域名系统(DNS)及其优化技术
💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 计算机网络中的域名系统(DNS)及其优化技术 计算机网络中的域名系统(DNS)及其优化…...
Matplotlib库中show()函数的用法
在Matplotlib库中使用show()函数是用于显示绘制的图形的函数。它将图形显示在屏幕上或保存到文件中。show()函数通常在绘制完图形后调用。 Matplotlib是一个用于绘制2D图形的Python库,它提供了丰富的绘图工具和函数,可以用于创建各种类型的图表…...
C#中object和dynamic
在C#中,object和dynamic都是用于存储不同类型值的类型,但它们之间存在一些关键的区别: object object是C#中的基元类型之一,是所有其他类型的最终基类。当你将一个值赋给object类型的变量时,编译器会执行装箱操作&am…...
Spring Cloud Eureka 服务注册与发现
Spring Cloud Eureka 服务注册与发现 一、Eureka基础知识概述1.Eureka两个核心组件2.Eureka 服务注册与发现 二、Eureka单机搭建三、Eureka集群搭建四、心跳续约五、Eureka自我保护机制 一、Eureka基础知识概述 1.Eureka两个核心组件 Eureka Server :服务注册中心…...
【WPF】Prism学习(三)
Prism Commands 1.复合命令(Composite Commanding) 这段内容主要介绍了在应用程序中如何使用复合命令(Composite Commands)来实现多个视图模型(ViewModels)上的命令。以下是对这段内容的解释: …...
保姆级教程:用CH34xSerCfg修改USB转串口芯片的VID/PID,解决驱动冲突和串口号固定问题
嵌入式开发实战:用CH34xSerCfg定制USB转串口设备标识与驱动管理 当你的工作台上同时连接着五个相同型号的USB转TTL模块,Windows设备管理器里COM端口像走马灯一样随机变换编号时;当团队协作开发中,每个成员需要固定识别自己的调试设…...
生物信息学逆向解析mRNA疫苗序列:从公开数据组装BNT-162b2与mRNA-1273的基因蓝图
1. 项目概述与背景解析 最近在生物信息学和疫苗研究领域,一个名为“NAalytics/Assemblies-of-putative-SARS-CoV2-spike-encoding-mRNA-sequences-for-vaccines-BNT-162b2-and-mRNA-1273”的项目引起了我的注意。这个项目标题看起来很长,但核心非常明确&…...
C++定时器避坑指南:线程安全、资源泄漏与时间轮参数怎么调?一次讲清楚
C定时器避坑指南:线程安全、资源泄漏与时间轮参数调优实战 在分布式系统和高并发场景中,定时器如同系统的心跳机制,其稳定性直接决定服务可靠性。去年某电商平台大促期间,由于定时任务堆积导致的雪崩效应,造成近千万损…...
告别标题栏!在RK3568 Buildroot固件上,让你的Qt应用开机全屏显示的保姆级教程
RK3568嵌入式全屏实战:从Weston配置到Qt应用独占显示的完整指南 在嵌入式Linux系统开发中,GUI应用的全屏显示往往成为工程师面临的第一个"拦路虎"。当你在RK3568平台上精心开发的Qt应用启动后,却发现屏幕顶部顽固地挂着Weston窗口管…...
KIVI开源工具箱:模块化设计赋能开发者效率提升
1. 项目概述:一个面向开发者的开源工具箱最近在GitHub上闲逛,发现了一个挺有意思的项目,叫KIVI。第一眼看到这个名字,我以为是某种新的UI框架或者设计系统,毕竟“KIVI”听起来有点像是“Kiwi”的变体,容易联…...
C# AI开发实战:BotSharp框架构建企业级NLP应用指南
1. 项目概述:当C#开发者遇上AI应用开发如果你是一名长期深耕.NET生态的开发者,最近看着Python在AI领域风生水起,心里是不是有点痒,又有点不甘?总觉得为了跑个模型、搭个智能对话,就得切到另一个完全不同的技…...
Go语言SDK开发实战:为AI编程助手Cursor构建高效API客户端
1. 项目概述:一个为AI编程助手Cursor定制的Go语言SDK如果你和我一样,日常重度依赖Cursor这类AI编程助手来提升开发效率,同时又是个Go语言的忠实拥趸,那你肯定遇到过这样的场景:想用Go写个脚本,自动化处理一…...
面试鸭:程序员面试备战工作台,构建结构化知识图谱与智能复习系统
1. 项目概述:一个面向求职者的“面试鸭”最近在技术社区里,看到不少朋友在讨论一个叫“mianshiya”的开源项目。乍一看这个名字,还以为是哪个美食博主分享的菜谱。点进去才发现,这其实是一个为程序员,特别是正在准备面…...
ARM Jazelle技术:硬件加速Java字节码执行详解
1. ARM Jazelle技术概述Jazelle技术是ARM架构中用于硬件加速Java字节码执行的关键扩展,最早出现在ARMv5TE架构中。这项技术通过在处理器内部集成Java字节码执行单元,实现了Java虚拟机(JVM)功能的硬件化。与传统的软件解释器相比,Jazelle能够将…...
基于WebSocket的机械爪远程控制桥接系统设计与实战
1. 项目概述:一个连接物理世界与数字世界的“机械爪”远程控制桥最近在捣鼓一个挺有意思的开源项目,叫lucas-jo/openclaw-bridge-remote。光看名字,你可能觉得这又是一个关于机器人或者机械臂的遥控项目,但实际深入进去࿰…...
