二、FIFO缓存

FIFO缓存

  • 1.FIFO缓存介绍
  • 2.FIFO缓存实现
  • 3.FIFO缓存总结

1.FIFO缓存介绍

FIFO(First-In-First-Out)缓存 是一种简单的缓存淘汰策略,它基于先进先出的原则来管理数据。当缓存达到容量限制并需要淘汰元素时,最先进入缓存的元素会被移除,以便为新元素腾出空间。
FIFO缓存的基本原则是:
①数据存储顺序:数据按照进入缓存的顺序排列(通常用队列实现)。最早插入的数据位于队列的前端,最新插入的数据位于队列的尾端。
②淘汰策略:当缓存已满,插入新数据时,队列前端的元素(最早插入的元素)被移除。

2.FIFO缓存实现

接下来我将通过c语言中的glib库来实现一个FIFO缓存结构。
首先给出结构体定义:

// FIFO 缓存结构体
struct fifoCache {
    GList* elem_queue;          // 缓存数据链表
    int max_size;               // 缓存容量
    int size;                   // 当前缓存大小
    void (*free_elem)(void*);   // 数据释放函数
    int (*match_elem)(void* elem, void* user_data); // 数据匹配函数
};

需要实现如下功能:

// 创建一个新的 FIFO 缓存
struct fifoCache* new_fifo_cache(int size, void (*free_elem)(void*),
                                 int (*match_elem)(void*, void*));

// 释放缓存及其中的所有元素
void free_fifo_cache(struct fifoCache* cache);

// 插入新数据到缓存
void fifo_cache_insert(struct fifoCache* cache, void* data);

// 查找元素(不改变数据顺序)
void* fifo_cache_lookup(struct fifoCache* cache, void* user_data);

// 条件删除满足用户自定义条件的元素
void fifo_cache_kicks(struct fifoCache* cache, void* user_data,
                      int (*func)(void* elem, void* user_data));

// 检查缓存是否已满
int fifo_cache_is_full(struct fifoCache* cache);

具体实现代码:

#include <stdlib.h>
#include <stdio.h>
#include "fifo_cache.h"

// 创建一个新的 FIFO 缓存
struct fifoCache* new_fifo_cache(int size, void (*free_elem)(void*),
                                 int (*match_elem)(void*, void*)) {
    struct fifoCache* cache = malloc(sizeof(struct fifoCache));
    cache->elem_queue = NULL;
    cache->max_size = size;
    cache->size = 0;
    cache->free_elem = free_elem;
    cache->match_elem = match_elem;
    return cache;
}

// 释放缓存及其中的所有元素
void free_fifo_cache(struct fifoCache* cache) {
    if (cache == NULL) return;
    if (cache->free_elem) {
        g_list_free_full(cache->elem_queue, cache->free_elem);
    } else {
        g_list_free(cache->elem_queue);
    }
    free(cache);
}

// 插入新数据到缓存
void fifo_cache_insert(struct fifoCache* cache, void* data) {
    if (cache->size == cache->max_size) {
        // 淘汰队列头部数据
        GList* head = g_list_first(cache->elem_queue);
        if (cache->free_elem) {
            cache->free_elem(head->data);
        }
        cache->elem_queue = g_list_delete_link(cache->elem_queue, head);
        cache->size--;
    }
    // 插入新数据到队列尾部
    cache->elem_queue = g_list_append(cache->elem_queue, data);
    cache->size++;
}

// 查找元素(不改变数据顺序)
void* fifo_cache_lookup(struct fifoCache* cache, void* user_data) {
    GList* elem = g_list_first(cache->elem_queue);
    while (elem) {
        if (cache->match_elem(elem->data, user_data)) {
            return elem->data;
        }
        elem = g_list_next(elem);
    }
    return NULL; // 未找到
}

// 条件删除满足用户自定义条件的元素
void fifo_cache_kicks(struct fifoCache* cache, void* user_data,
                      int (*func)(void* elem, void* user_data)) {
    GList* elem = g_list_first(cache->elem_queue);
    while (elem) {
        if (func(elem->data, user_data)) {
            if (cache->free_elem) {
                cache->free_elem(elem->data);
            }
            cache->elem_queue = g_list_delete_link(cache->elem_queue, elem);
            cache->size--;
            break;
        }
        elem = g_list_next(elem);
    }
}

// 检查缓存是否已满
int fifo_cache_is_full(struct fifoCache* cache) {
    return cache->size >= cache->max_size;
}

测试代码:

#include "fifo_cache.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 自定义数据类型
typedef struct {
    char* name;
} Data;

// 数据释放函数
void free_data(void* data) {
    Data* d = (Data*)data;
    printf("[Free] Name = %s\n", d->name);
    free(d->name);
    free(d);
}

// 数据匹配函数
int match_data(void* elem, void* user_data) {
    Data* d = (Data*)elem;
    char* target = (char*)user_data;
    return strcmp(d->name, target) == 0;
}

int main() {
    printf("---- FIFO Cache Test ----\n");

    struct fifoCache* cache = new_fifo_cache(3, free_data, match_data);

    // 插入数据
    printf("[Insert] Alice, Bob, Charlie\n");
    Data* a = malloc(sizeof(Data)); a->name = strdup("Alice");
    Data* b = malloc(sizeof(Data)); b->name = strdup("Bob");
    Data* c = malloc(sizeof(Data)); c->name = strdup("Charlie");
    fifo_cache_insert(cache, a);
    fifo_cache_insert(cache, b);
    fifo_cache_insert(cache, c);

    // 查找数据
    printf("Looking up: Bob\n");
    Data* result = (Data*)fifo_cache_lookup(cache, "Bob");
    if (result) printf("Found: %s\n", result->name);

    // 插入新数据,触发淘汰
    printf("[Insert] "Dave"\n");
    Data* d = malloc(sizeof(Data)); d->name = strdup("Dave");
    fifo_cache_insert(cache, d);

    // 查找被淘汰的数据
    printf("Looking up: Alice\n");
    result = (Data*)fifo_cache_lookup(cache, "Alice");
    if (!result) printf("Alice has been evicted.\n");

    free_fifo_cache(cache);
    printf("---- Test Complete ----\n");
    return 0;
}

测试结果:
在这里插入图片描述
同样的,上面的FIFO缓存支持任意的数据类型,具有高度的通用性和灵活性。

3.FIFO缓存总结

FIFO缓存应用:

应用场景说明
任务调度在操作系统中,FIFO 用于管理任务队列,确保任务按照到达的顺序执行。
页面置换在内存管理中,FIFO 用于页面置换,淘汰最早加载的页面,释放内存空间。
网络数据包缓存在网络交换机和路由器中,FIFO 用于管理数据包队列,按照顺序传输或丢弃数据包。
日志管理适合简单的日志记录,按照记录顺序缓存和清理日志数据。
数据缓冲区在流式数据处理中,FIFO 用于临时存储数据,确保数据按顺序读取和处理。
消息队列实现生产者-消费者模型中的消息传递,保证消息按插入顺序进行处理。

FIFO缓存优缺点:

优点说明
实现简单基于队列数据结构,逻辑清晰,易于实现。
插入和删除效率高在队列的尾部插入、头部删除,时间复杂度为 O(1)。
公平性数据按照到达顺序被处理,没有优先级差异。
适合访问模式简单、数据均匀的场景适合不需要热点数据的简单缓存需求。
缺点说明
无法处理热点数据即使频繁访问的数据也不会改变淘汰顺序,可能被淘汰。
缓存利用率低在访问模式复杂的场景下,缓存命中率较低。
不考虑数据的访问频率或时间与 LRU 或 LFU 相比,无法根据访问频率或时间进行智能淘汰。
适用于简单场景不适合需要高度优化性能的复杂系统。

总结:FIFO 缓存是一种简单高效的缓存淘汰策略,适用于数据访问均匀且热点数据不明显的场景。它的实现依赖于队列结构,逻辑清晰,插入和删除操作性能高。然而,在访问热点数据频繁的应用中,FIFO 的性能可能不如 LRU 和 LFU 等策略。在实际应用中,FIFO 适合简单场景,比如任务调度、数据缓冲区 和 日志管理,但在复杂缓存场景下,可能需要结合其他策略实现更高的缓存命中率。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

王佩丰24节Excel学习笔记——第十四讲:日期函数

【以 Excel2010 系列学习&#xff0c;用 Office LTSC 专业增强版 2021 实践】 【本章小技巧】 掌握date()日期函数&#xff0c;配合年月日时分秒使用使用datedif()函数计算两个日期之前的差&#xff0c;重点记住参数三&#xff0c;差的值以哪种类型显示。使用weeknum/weekday,…

python--在服务器上面创建conda环境

今天刚开始使用服务器的时候使用上面的公共环境发现老师缺少模块&#xff0c; [guoyupingcins195 ~]$ conda --version Traceback (most recent call last): File "/home/miniconda3/bin/conda", line 12, in <module> from conda.cli import main Fil…

Trimble天宝三维激光扫描仪在建筑工程竣工测量中的应用【沪敖3D】

竣工测量是建筑项目竣工阶段的一个至关重要的环节&#xff0c;它为建筑工程的质量验收和成果核查提供了核心的参考依据。传统的竣工测量方法&#xff0c;如全站仪测量&#xff0c;主要依赖于现场人工操作&#xff0c;存在一些明显的局限性&#xff0c;例如作业时间长、工作量大…

SEO初学者-搜索引擎如何工作

搜索引擎基础搜索引擎是如何建立索引的搜索引擎如何对网页进行排名搜索引擎是如何个性化搜索结果的 搜索引擎的工作方式是使用网络爬虫抓取数十亿个页面。爬虫也称为蜘蛛或机器人&#xff0c;它们在网络上导航并跟踪链接以查找新页面。然后&#xff0c;这些页面会被添加到搜索引…

react中实现导出excel文件

react中实现导出excel文件 一、安装依赖二、实现导出功能三、自定义列标题四、设置列宽度五、样式优化1、安装扩展库2、设置样式3、扩展样式功能 在 React 项目中实现点击按钮后导出数据为 Excel 文件&#xff0c;可以使用 xlsx 和 file-saver 这两个库。 一、安装依赖 在项目…

Latex中表格添加底部文本注释并调整对齐

如何实现从第一个表到第三个表的转换&#xff0c; 其中主要涉及到两点&#xff1a; &#xff08;1&#xff09;底部脚注与表格自动对齐并缩进换行 &#xff08;2&#xff09;表格自适应页面宽度 底部脚注的对齐与换行缩进需要用到 \usepackage{threeparttable} \usepackage{…

MySQL基础 -----MySQL数据类型

目录 INT类型 tinyint类型 类型大小范围 测试tinyint类型数据 float类型 测试&#xff1a; 测试正常数据范围的数据 测试插入范围超过临界值的数据&#xff1a; 测试float类型的四舍五入 ​编辑 decimal类型 同样测试&#xff1a; 字符串类型 char类型 测试&…

【HarmonyOS NEXT】Web 组件的基础用法以及 H5 侧与原生侧的双向数据通讯

关键词&#xff1a;鸿蒙、ArkTs、Web组件、通讯、数据 官方文档Web组件用法介绍&#xff1a;文档中心 Web 组件加载沙箱中页面可参考我的另一篇文章&#xff1a;【HarmonyOS NEXT】 如何将rawfile中文件复制到沙箱中_鸿蒙rawfile 复制到沙箱-CSDN博客 目录 如何在鸿蒙应用中加…

ONES 功能上新|ONES Copilot、ONES Wiki 新功能一览

ONES Copilot 可基于工作项的标题、描述、属性信息&#xff0c;对工作项产生的动态和评论生成总结。 针对不同类型的工作项&#xff0c;总结输出的内容有对应的侧重点。 应用场景&#xff1a; 在一些流程步骤复杂、上下游参与成员角色丰富的场景中&#xff0c;工作项动态往往会…

使用qemu搭建armv7嵌入式开发环境

目录 目录 1 概述 2 环境准备 2.1 vexpress系列开发板介绍 2.2 安装工具 2.2.1 安装交叉工具链 2.2.2 安装qemu 2.2.3 安装其他工具 3 启动uboot 3.1 uboot下载与编译 3.1.1 下载 3.1.2 编译 3.2 使用qemu启动uboot 4 启动kernel 4.1 下载和编译kernel 4.1.1 下…

28.操作数据库

第三方库pymysql 使用安装命令 pip install pymysql 连接数据库、选择库、获取游标&#xff0c;执行创建表语句 from pymysql import Connection# 获取到mysql数据库连接对象 conn Connection(host"localhost", passwd"123456", user"root", …

docker(wsl)命令 帮助文档

WSL wsl使用教程 wsl -l -v 列出所有已安装的 Linux 发行版 wsl -t Ubuntu-22.04 --shutdown 关闭所有正在运行的WSL发行版。如果你只想关闭特定的发行版 wsl -d Ubuntu-22.04 登录到Ubuntu环境 wsl --list --running 查看正在wsl中运行的linux发行版 wsl --unregister (系统名…

JVM系列之内存区域

每日禅语 有一位年轻和尚&#xff0c;一心求道&#xff0c;多年苦修参禅&#xff0c;但一直没有开悟。有一天&#xff0c;他打听到深山中有一古寺&#xff0c;住持和尚修炼圆通&#xff0c;是得道高僧。于是&#xff0c;年轻和尚打点行装&#xff0c;跋山涉水&#xff0c;千辛万…

【ADS射频电路学习笔记】2.阻抗匹配电路设计

本节课学习smith圆图匹配 1.史密斯圆图各功能介绍 首先调出s参数的控件 并增加两个端口 调出smith chart matching的控件 连接好端口在ADS中&#xff0c;默认是从负载端&#xff08;term2&#xff09;向源端&#xff08;term1&#xff09;做匹配的。 调节s参数控件的的频率扫…

springcloud-gateway获取应用响应信息乱码

客户端通过springcloud gateway跳转访问tongweb上的应用&#xff0c;接口响应信息乱码。使用postman直接访问tongweb上的应用&#xff0c;响应信息显示正常。 用户gateway中自定义了实现GlobalFilter的Filter类&#xff0c;在该类中获取了上游应用接口的响应信息&#xff0c;直…

泷羽sec学习打卡-brupsuite8伪造IP和爬虫审计

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都 与本人无关,切莫逾越法律红线,否则后果自负 关于brupsuite的那些事儿-Brup-FaskIP 伪造IP配置环境brupsuite导入配置1、扩展中先配置python环境2、安…

【优选算法---分治】快速排序三路划分(颜色分类、快速排序、数组第K大的元素、数组中最小的K个元素)

一、颜色分类 题目链接: 75. 颜色分类 - 力扣&#xff08;LeetCode&#xff09; 题目介绍&#xff1a; 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地 对它们进行排序&#xff0c;使得相同颜色的元素相邻&#xff0c;并按照红色、白色、蓝色顺序…

【译】仅有 Text2SQL 是不够的: 用 TAG 统一人工智能和数据库

原文地址&#xff1a;Text2SQL is Not Enough: Unifying AI and Databases with TAG 摘要 通过数据库为自然语言问题提供服务的人工智能系统有望释放出巨大的价值。此类系统可让用户利用语言模型&#xff08;LM&#xff09;的强大推理和知识能力&#xff0c;以及数据管理系统…

leetcode 面试经典 150 题:长度最小的子数组

链接长度最小的子数组题序号209题型数组解题方法滑动窗口难度中等 题目 给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl1, …, numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件…

vue 设置 VUE_APP_TITLE 打包部署后不生效

VUE_APP_TITLE 名门望族云科技有限公司网站 这里的 名门望族云科技有限公司网站 两边不能加 (单引号) 部署后,浏览器刷新网站根目录