【从零实现高并发内存池】thread cache、central cache 和 page cache 回收策略详解
📢博客主页:https://blog.csdn.net/2301_779549673
📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson
📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📢本文由 JohnKi 原创,首发于 CSDN🙉
📢未来很长,值得我们全力奔赴更美好的生活✨
文章目录
- 🏳️🌈一、thread cache 回收策略
- 🏳️🌈二、central cache 回收策略
- 🏳️🌈三、page cahce 回收策略
- 👥总结
🏳️🌈一、thread cache 回收策略
- 随着我们对 thread cache 的使用,会有越来越多的内存块从 central cache 中被申请,然后等使用完后再返还给 thread cahce,挂在对应的自由链表中,继续等待使用
- 但是倘若我们有一个自由链表后面挂着的内存块十分地长,长到远远超过当前进程所需,那么就会造成内存地占用,导致浪费,使有的地方的内存不够使用
- 所以我们需要指定一个 thread cache 回收策略,针对太长的自由链表进行回收,返还给 central cache,使内存池更加高效
// 释放内存对象
void ThreadCache::Deallocate(void* ptr, size_t size) {assert(ptr);assert(size <= MAX_BYTES);// 找出对应映射的链表桶,并将对象放入链表中size_t index = SizeClass::Index(size);_freeLists[index].Push(ptr);// 当链表过长时,回收内存到中心缓存if (_freeLists[index].MaxSize() >= _freeLists[index].MaxSize()) {ListTooLong(_freeLists[index], size);}
}
当自由链表的长度大于一次批量申请的对象时,我们具体的做法就是,从该自由链表中取出一次批量个数的对象,然后将取出的这些对象还给central cache中对应的span即可。
// 释放对象时,链表过⻓时,回收内存回到中⼼缓存
void ThreadCache::ListTooLong(FreeList& list, size_t size) {void* start = nullptr;void* end = nullptr;// 弹出一段内存对象list.PopRange(start, end, list.MaxSize());CentralCache::GetInstance()->ReleaseListToSpans(start, size);
}
对于 ListTooLong 部分的代码,我们可以先确认 头尾地址,将这段内存对象从链表中弹出,再通过 central cache 返还给 page cache 处理
因此我们也就需要为 list 对象新添一个弹出指定大小内存的方法 PopRange
void PopRange(void*& start, void*& end, size_t maxSize, size_t n) {assert(n >= _size);start = _freeList;end = start;for (size_t i = 0; i < n - 1; ++i) {end = NextObj(end);}_freeList = NextObj(end);NextObj(end) = nullptr;_size -= n;
}
这部分的方法思路就是
- 将 链表头节点作为 返回值的头地址
- 然后再 利用循环,不断向后扩大 这个返回内存条的范围
- 最后再 将剩余内存条的头节点 作为 链表新头节点
- 将 链表的大小剪去弹出的大小
// 管理切分好的小对象的自由链表
class FreeList {public:void Push(void* obj) {assert(obj);// 头插NextObj(obj) = _freeList;_freeList = obj;++_size;}// 将新分配的内存块放入链表中void PushRange(void* start, void* end, size_t n) {NextObj(end) = _freeList;_freeList = start;_size += n;}void PopRange(void*& start, void*& end, size_t n) {assert(n >= _size);start = _freeList;end = start;for (size_t i = 0; i < n - 1; ++i) {end = NextObj(end);}_freeList = NextObj(end);NextObj(end) = nullptr;_size -= n;}void* Pop() {assert(_freeList);// 头删void* obj = _freeList;_freeList = NextObj(obj);--_size;return obj;}bool Empty() {return (_freeList == nullptr);}size_t& MaxSize() {return _maxSize;}private:void* _freeList = nullptr;size_t _maxSize = 1;size_t _size = 0;
};
🏳️🌈二、central cache 回收策略
当thread cache中某个自由链表太长时,会将自由链表当中的这些对象还给central cache中的span。
注意:还给central cache的这些对象不一定都是属于同一个span的。
central cache
中的每个哈希桶当中可能都不止一个 span
,因此当我们计算出还回来的对象应该还给 central cache
的哪一个桶后,还需要知道这些对象到底应该还给这个桶当中的哪一个span。
如何找到一个对象对应的span?
虽然我们现在可以通过对象的地址得到其所在的页号,但是我们还是不能知道这个对象到底属于哪一个span。因为一个span管理的可能是多个页。
为了解决这个问题,我们可以建立页号和span之间的映射 。由于这个映射关系在 page cache 进行 span 的合并时也需要用到,因此我们直接将其存放到 page cache 里面。这时我们就需要在 PageCache 类当中添加一个映射关系了,这里可以用 unordered_map 进行实现,并且添加一个函数接口,用于让 central cache 获取这里的映射关系。
// 单例模式
class PageCache{
public:// 获取从对象到span的映射Span* MapObjectToSpan(void* obj);
private:std::unordered_map<PAGE_ID, Span*> _idSpanMap;
};
因此,我们需要在 每当page cache分配span给central cache时,记录一下页号和span之间的映射关系。此后当thread cache还对象给central cache时,才知道应该具体还给哪一个span
分别应该在
- page cache 在返回这个 k 页的 span 给 central cache 时
- 当 central cache 在调用 NewSpan 接口向 page cache 申请 k 页的 span 时
// 获取一个 k 页的 span
Span* PageCache::NewSpan(size_t k) {assert(k > 0 && k < NPAGES);// 先检查第 k 个桶里面有没有 spanif (!_spanLists[k].Empty()) {Span* kSpan = _spanLists->PopFront();// 建立 页号 与 span 的映射关系,方便 central cache 回收小块内存查找对应的 spanfor (PAGE_ID i = 0; i < kSpan->_n; ++i) {_idSpanMap[kSpan->_PAGEID + i] = kSpan;}return kSpan;}// 检查一下后面的桶里面有没有 span,如果有可以把他进行切分for (size_t i = k + 1; i < NPAGES; ++i) {// 如果后面的桶里面有 span,这个 span 是肯定大于 k 页的if (!_spanLists[i].Empty()) {// 弹出第 i 个桶的第一个 spanSpan* nSpan = _spanLists[i].PopFront();// 进行切分,切分成一个 k 页的 span 和一个 i-k 页的 spanSpan* kSpan = new Span;kSpan->_PAGEID = nSpan->_PAGEID;kSpan->_n = k;nSpan->_PAGEID += k;nSpan->_n -= k;// 将剩余的代码挂到对应的映射位置上_spanLists[nSpan->_n].PushFront(nSpan);for (PAGE_ID i = 0; i < kSpan->_n; ++i) {_idSpanMap[kSpan->_PAGEID + i] = kSpan;}return kSpan;}}// 走到这个位置就说明后面没有大页的 span 了// 就需要去找堆要一个 128 页的 spanSpan* bigSpan = new Span;void* ptr = SystemAlloc(NPAGES - 1);bigSpan->_PAGEID = (PAGE_ID)ptr >> PAGE_SHIFT;bigSpan->_n = NPAGES - 1;_spanLists[bigSpan->_n].PushFront(bigSpan);return NewSpan(k);
}
此时我们就可以通过对象的地址找到该对象对应的span了,直接将该对象的地址除以页的大小得到页号,然后在unordered_map当中找到其对应的span即可。
Span* PageCache::MapObjectToSpan(void* obj) {PAGE_ID id = ((PAGE_ID)obj >> PAGE_SHIFT);auto ret = _idSpanMap.find(id);if(ret != _idSpanMap.end())return ret->second;else {assert(false);return nullptr;}
}
当我们要通过某个页号查找其对应的span时,该页号与其span之间的映射一定是建立过的,如果此时我们没有在unordered_map当中找到,则说明我们之前的代码逻辑有问题 ,因此当没有找到对应的span时可以直接用断言结束程序,以表明程序逻辑出错。
// 将⼀定数量的对象释放到span跨度
void CentralCache::ReleaseListToSpans(void* start, size_t size) {size_t index = SizeClass::Index(size);_spanLists[index]._mtx.lock();while (start) {void* next = NextObj(start); // 记录下一个节点// 获取从对象到 span 的映射Span* span = PageCache::GetInstance()->MapObjectToSpan(start);// 将对象头插到 span 的自由链表中NextObj(start) = span->_freeList;span->_freeList = start;// 更新被分配给 thread cache的对象数量span->_userCount--;// 当这个span分配出去的对象数量为0时,说明这个span已经没有被分配出去的对象了,if (span->_userCount == 0) {// 此时这个span就可以再回收给 page cache 了_spanLists[index].Erase(span);span->_freeList = nullptr; // 自由链表制空span->_next = nullptr;span->_prev = nullptr;// 释放 span 给 page cache 时,使用 page cache 的锁即可,这是把 central cache桶锁解掉_spanLists[index]._mtx.unlock(); // 解除桶锁PageCache::GetInstance()->_pageMtx.lock(); // 加锁PageCache::GetInstance()->ReleaseSpanToPageCache(span); PageCache::GetInstance()->_pageMtx.unlock(); // 解锁_spanLists[index]._mtx.lock(); // 加桶锁}start = next;}_spanLists[index]._mtx.unlock();
}
在central cache
还span给 page cache
时也存在锁的问题,此时需要>先将 central cache
中对应的桶锁解掉,然后再加上 page cache
的大锁之后才能进入 page cache
进行相关操作,当处理完毕回到 central cache
时,除了将 page cache
的大锁解掉,还需要立刻加上 central cache
对应的桶锁,然后将还未还完对象继续还给 central cache
中对应的span。
🏳️🌈三、page cahce 回收策略
-
如果 central cache 中有某个 span 的 _useCount 减到0了,那么 central cache 就需要将这个 span 还给 page cache 了。
-
这个过程看似是非常简单的,page cache只需将还回来的span挂到对应的哈希桶上就行了。但实际为了缓解内存碎片的问题,page cache还需要尝试将还回来的span与其他空闲的span进行合并。
page cache进行前后页的合并分析
合并的过程可以分为向前合并和向后合并。如果还回来的span的起始页号是num,该span所管理的页数是n。
- 在向前合并时,就需要判断第num-1页对应span是否空闲,如果空闲则可以将其进行合并,并且合并后还需要继续向前尝试进行合并,直到不能进行合并为止。
- 在向后合并时,就需要判断第num+n页对应的span是否空闲,如果空闲则可以将其进行合并,并且合并后还需要继续向后尝试进行合并,直到不能进行合并为止。
当我们通过页号找到其对应的span时,这个span此时可能挂在page cache,也可能挂在central cache。而在合并时我们只能合并挂在page cache的span,因为挂在central cache的span当中的对象正在被其他线程使用。
我们可以在span结构中再增加一个_isUse成员,用于标记这个span是否正在被使用,而当一个span结构被创建时,默认该span是没有被使用的。
// 管理多个连续页大块内存跨度结构
struct Span {PAGE_ID _PAGEID = 0; // 大块内存起始页的页号size_t _n = 0; // 页的数量Span* _next = nullptr; // 双向链表的结构Span* _prev = nullptr; size_t _userCount = 0; // 已分配给 Thread Cache 的小块内存数量void* _freeList = nullptr; // 自由链表头指针(指向未分配的小块内存)bool _isused = false; // 是否在被使用
};
因为当一个span在尝试进行合并时,
- 如果是往前合并,那么只需要通过一个span的尾页找到这个span,
- 如果是向后合并,那么只需要通过一个span的首页找到这个span。
也就是说,在进行合并时我们只需要用到span与其首尾页之间的映射关系就够了。
void PageCache::ReleaseSpanToPageCache(Span* span) {// 对 span 前后的页,尝试进行合并,缓解内存碎片问题// 向前合并while (1) {PAGE_ID prevId = span->_PAGEID - 1;auto ret = _idSpanMap.find(prevId);// 前面的页号没有,不合并了if (ret == _idSpanMap.end()) {break;}// 前面相邻页的span在使用,不合并了Span* prevSpan = ret->second;if (ret->second->_isused == true) {break;}// 合并出超过 128 页的 span 没办法管理,不合并了if (prevSpan->_n + span->_n > NPAGES) {break;}span->_PAGEID = prevSpan->_PAGEID;span->_n += prevSpan->_n;_spanLists[prevSpan->_n].Erase(prevSpan);delete prevSpan;}// 向后合并while (1) {PAGE_ID nextId = span->_PAGEID + span->_n; auto ret = _idSpanMap.find(nextId);if (ret == _idSpanMap.end()) {break;}Span* nextSpan = ret->second;if (nextSpan->_isused == true) {break;}if(nextSpan->_n + span->_n >> NPAGES - 1){break;}span->_n += nextSpan->_n;_spanLists[nextSpan->_n].Erase(nextSpan);delete nextSpan;}_spanLists[span->_n].PushFront(span);span->_isused = false;_idSpanMap[span->_PAGEID] = span;_idSpanMap[span->_PAGEID + span->_n - 1] = span;
}
👥总结
本篇博文对 【从零实现高并发内存池】thread cache、central cache 和 page cache 回收策略详解 做了一个较为详细的介绍,不知道对你有没有帮助呢
觉得博主写得还不错的三连支持下吧!会继续努力的~
相关文章:
【从零实现高并发内存池】thread cache、central cache 和 page cache 回收策略详解
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
算法5-16 对二进制字符串解码
输入样例: 5 a 4 b 3 c 2 w 1 z 1 100001110101101101100111输出样例: baaacabwbzc ac代码: #include<iostream> #include<queue> #include<map> using namespace std; const int N10010; int idx; int a[N][2]; char b…...
[MySQL数据库] InnoDB存储引擎(三): 内存结构详解
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...
TDengine 存储引擎剖析:数据文件与索引设计(一)
TDengine 存储引擎简介 在物联网、工业互联网等快速发展的今天,时间序列数据呈爆发式增长。这些数据具有产生频率高、依赖采集时间、测点多信息量大等特点,对数据存储和处理提出了极高要求。TDengine 作为一款高性能、分布式、支持 SQL 的时序数据库&am…...
CentOS更换yum源
CentOS更换yum源 视频教程: https://www.bilibili.com/video/BV1yWaSepE6z/?spm_id_from333.1007.top_right_bar_window_history.content.click 步骤: 第一步: cd /etc/yum.repos.d第二步:cp CentOS-Base.repo CentOS-Base.repo…...
【Kubernetes基础--持久化存储原理】--查阅笔记5
目录 持久化存储机制PV 详解PV 关键配置参数PV 生命周期的各个阶段 PVC 详解PVC 关键配置参数PV 和 PVC 的生命周期 StorageClass 详解StorageClass 关键配置参数设置默认的 StorageClass 持久化存储机制 k8s 对于有状态的容器应用或对数据需要持久化的应用,不仅需…...
数据库子查询实验全解析
目录 一、验证性实验:夯实基础(一)查询同班学生信息(二)查询成绩相关信息(三)查询课程选课人数(四)相关子查询(五)EXISTS嵌套子查询(六…...
HTML:表格数据展示区
<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>人员信息表</title><link rel"styl…...
webgl入门实例-08索引缓冲区的基本概念
WebGL 索引缓冲区 (Index Buffer) 索引缓冲区(也称为元素数组缓冲区)是WebGL中一种优化渲染性能的重要机制,它允许您重用顶点数据来绘制复杂的几何图形。 基本概念 索引缓冲区的工作原理: 您创建一个顶点缓冲区(包含所有顶点数据)然后创建一个索引缓…...
大数据应用开发——大数据平台集群部署
目录 前言 目录 基础环境 安装虚拟机 基础环境 VMware Workstation 虚拟机版本 : centos7 主机名 ip 用户名 密码 master192.168.245.100root123456slave1192.168.245.101root123456slave2192.168.245.102root123456 安装虚拟机 安装 名称、路径自己改 我有16核&…...
GPT对话UI--通义千问API
GPT对话UI 项目介绍 一个基于 GPT 的智能对话界面,提供简洁优雅的用户体验。本项目使用纯前端技术栈实现,无需后端服务器即可运行。 功能特点 💬 实时对话:支持与 AI 进行实时对话交互🌓 主题切换:支持…...
智能体数据分析
数据概览: 展示智能体的累计对话次数、累计对话用户数、对话满意度、累计曝光次数。数据分析: 统计对话分析、流量分析、用户分析、行为分析数据指标,帮助开发者完成精准的全面分析。 ps:数据T1更新,当日12点更新前一天…...
泛型算法——只读算法(一)
在 C 标准库中,泛型算法的“只读算法”指那些 不会改变它们所操作的容器中的元素,仅用于访问或获取信息的算法,例如查找、计数、遍历等操作。 accumulate std::accumulate()是 C 标准库**numeric**头文件中提供的算法,用于对序列…...
树莓派超全系列教程文档--(29)config.txt介绍
config.txt介绍 什么是 config.txt ?文件格式高级功能include条件过滤 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 什么是 config.txt ? Raspberry Pi 设备使用名为 config.txt 的配置文件,而不是传统 PC …...
第十六届蓝桥杯大赛软件赛省赛 C++ 大学 B 组 部分题解
赛时参加的是Python组,这是赛后写的题解,还有两题暂时还不会,待更新 题目链接题目列表 - 洛谷 | 计算机科学教育新生态 A 移动距离 答案:1576 C 可分解的正整数 Python3 import itertools from functools import cmp_to_ke…...
C++栈与堆内存详解:Visual Studio实战指南
C++栈与堆内存详解:Visual Studio实战指南 IDE环境:Visual Studio 2022 一、内存分区与核心概念 在C++程序中,内存分为**栈(Stack)和堆(Heap)**两大核心区域,两者的管理方式、生命周期和适用场景差异显著。 1. 栈内存(Stack Memory) • 特性: • 自动管理:由编…...
在Ubuntu服务器上部署xinference
一、拉取镜像 docker pull xprobe/xinference:latest二、启动容器(GPU) docker run -d --name xinference -e XINFERENCE_MODEL_SRCmodelscope -p 9997:9997 --gpus all xprobe/xinference:latest xinference-local -H 0.0.0.0 # 启动一个新的Docker容…...
非洲电商争夺战:中国闪电战遭遇本土游击队的降维打击
2024年5月,南非电商市场爆发史诗级对决——Temu闪电突袭下载量破百万,却在30天内遭遇Takealot的本土化反击致留存率腰斩。这场价值500亿美元市场的攻防战,揭开了非洲电商最残酷的生存法则:低价利刃砍不动本土化铁壁。 一、跨境模式…...
亚瑟阿伦36问
问 36 个问题,你就能爱上一个人,对方也能爱上你。 第一组 聚焦个人背景与价值观 例如“你最感激生命中的什么?”、“如果可以改变成长经历,你会改变什么?” 1、如果可以跟世上任何人共进晚餐,你会选择谁&…...
Ubuntu 20.04.6编译安装COMFAST CF-AX90无线网卡驱动
目录 0 前言 1 CF-AX90无线网卡驱动 1.1 驱动下载 1.2 驱动准备 2 编译安装驱动 2.1 拷贝驱动依赖到系统 2.2 驱动安装编译 3 重启 0 前言 COMFAST CF-AX90或者说AIC8800D80的Linux版本驱动不支持高版本的linux内核,实测目前仅支持最高5.15的内核。Ubuntu2…...
函数的极限与连续(强化和真题)
强化错题如下:...
4.15【Q】netsafe
我正在学习网络空间安全,” Cookie:使用防hash技术防御SYN泛洪攻击,减少服务器内存消耗“什么意思?什么是SYN泛洪攻击?什么又是防hash技术防御? ?详细解释,越细节越好 连接成功率 …...
多个路由器互通(静态路由)无单臂路由(简单版)
多个路由器互通(静态路由)无单臂路由(简单版) 开启端口并配ip地址 维护1 Router>en Router#conf t Router(config)#int g0/0 Router(config-if)#no shutdown Router(config-if)#ip address 192.168.10.254 255.255.255.0 Ro…...
opencv HSV的具体描述
色调H: 使用角度度量,取值范围为0\~360,从红色开始按逆时针方向计算,红色为0,绿色为120,蓝色为240。它们的补色是:黄色为60,青色为180,紫色为300。通过改变H的值&#x…...
ubuntu磁盘挂载
1、查看磁盘设备及分区 命令:列出所有块设备(磁盘及分区) lsblk 0表示此块未挂载 2、格式化分区 sudo mkfs.ext4 /dev/sdb 注意sdb换成自己的块名称 3、创建挂载点目录 sudo mkdir -p /mnt/data4、永久挂载 sudo blkid /dev…...
Visual Studio C++引入第三方库
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要整理visual studio C导入第三方库的注意事项与操作 bilibili配套视频:【visual studio C导入第三方库-哔哩哔哩】 https://b23.tv/vphfXnv 运行库选项 右键项目 -> 属性 -> C/C ->代码生成->…...
2025中国移动云智算大会回顾:云智变革,AI+跃迁
4月10日,2025中国移动云智算大会在苏州举办。会上,中国移动开启“由云向智”新范式,以“智”为核心开辟算网新生态,彰显其在AI新时代的战略远见与技术引领力。 “云智算”将如何通过算网基础设施与人工智能核心技术的深度融合&am…...
海珠区公示人工智能大模型应用示范区第二批资金奖励企业名单,助力产业蓬勃发展
2025 年 4 月 15 日,广州琶洲人工智能与数字经济试验区管理委员会在广州市海珠区人民政府门户网站发布重要通知,对人工智能大模型应用示范区政策兑现工作(第二批)(大模型专题)资金奖励企业名单予以公示。这…...
golang处理时间的包time一次性全面了解
本文旨在对官方time包有个全面学习了解。不钻抠细节,但又有全面了解,重点介绍常用的内容,一些低频的可能这辈子可能都用不上。主打一个花最少时间办最大事。 Duration对象: 两个time实例经过的时间,以长度为int64的纳秒来计数。 常见的durati…...
文件的加密与解密学习笔记
一些可能想知道的: cryptography库:密码学工具包 Fernet 是crytography 里的一个模块,用于对称加密 with open() as file #为了保证无论是否出错都能正确地关闭文件,与try...finally...相同 open() #用于读文件(默认…...
《TCP/IP网络编程》学习笔记 | Chapter 24:制作 HTTP 服务器端
《TCP/IP网络编程》学习笔记 | Chapter 24:制作 HTTP 服务器端 《TCP/IP网络编程》学习笔记 | Chapter 24:制作 HTTP 服务器端HTTP 概要理解 Web 服务器端无状态的 Stateless 协议请求消息(Request Message)的结构响应消息&#x…...
Apache POI(笔记)
介绍: 坐标: 写入Excel表格: 读取Excel表格:...
Table类型的表单
形如下面的图片 1 label与prop属性 const columns[{label: "文件名",prop: "fileName",scopedSlots: "fileName",},{ label: "删除时间",prop: "recoveryTime",width: "200",},{ label: "大小",prop:…...
Spring 中的验证、数据绑定和类型转换
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
【技术派后端篇】canal实现MySQL/Redis缓存一致性
1 前言 在探讨如何利用canal实现MySQL/Redis缓存一致性之前,强烈建议大家先阅读以下几篇相关文章,因为本文是基于这些文章的基础上展开的: 《深度剖析 MySQL 与 Redis 缓存一致性:理论、方案与实战》 :该文详细阐述了…...
华清远见STM32F103智能小车重磅上线!循迹避障红外遥控WiFi远程控制,0基础小白从入门到单片机软硬件项目实战!
STM32F103智能云控小车是由华清远见倾力打造的一款多功能智能小车,专为高校教学、学生毕业设计、创新竞赛、单片机入门学习及项目实践量身定制。这款小车集红外遥控、远程物联网控制、智能巡线、高精度避障和交互式显示屏五大核心功能于一体,融合了物联网…...
李飞飞团队新作WorldScore:“世界生成”能力迎来统一评测,3D/4D/视频模型同台PK
从古老神话中对世界起源的幻想,到如今科学家们在实验室里对虚拟世界的构建,人类探索世界生成奥秘的脚步从未停歇。如今,随着人工智能和计算机图形学的深度融合,我们已站在一个全新的起点,能够以前所未有的精度和效率去…...
seaborn库详解
Seaborn 是一个基于 Python 的统计数据可视化库,它建立在 matplotlib 之上,旨在提供更高级、更美观、更具统计意义的可视化功能。 CONTENT 1. 单变量分布可视化功能代码 2. 双变量联合分布可视化功能代码 3. 分类数据柱状图可视化功能代码 4. 箱线图可视…...
UNACMS PHP对象注入漏洞复现(CVE-2025-32101)(附脚本)
免责申明: 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 前言…...
应用篇02-镜头标定(上)
本节主要介绍相机的标定方法,包括其内、外参数的求解,以及如何使用HALCON标定助手实现标定。 计算机视觉——相机标定(Camera Calibration)_摄像机标定-CSDN博客 1. 原理 本节介绍与相机标定相关的理论知识,不一定全,可以参考相…...
游戏引擎学习第230天
回顾并为今天的内容定下基调 今天是我们进行“排序”工作的第二天。昨天我们在渲染器中实现了排序功能。这其实是从一开始就知道必须做的事情,只是一直没有合适的时机。而昨天终于迎来了这个时机,不知道为什么,可能就是突然有了冲动和想法&a…...
3.串口通信之SPI
—>1.串口通信之UART见这篇<— —>2.串口通信之IIC见这篇<— 1.SPI特点 SPI(Serial Peripheral Interface)即串行外设接口,有4条总线,分别是SCLK(SPI Clock),MISO(Master Input Slave Output),MOSI(Mast…...
无人机姿态稳定与动态控制模块概述!
一、设计难点 1. 动态算力需求与硬件能力的不匹配** 无人机边缘计算设备通常受限于体积和重量,导致其计算单元(如CPU、GPU)的算力有限,难以应对突发的高负载任务(如实时图像处理、AI推理)。 挑战&am…...
【shell】终端文本的颜色和样式打印
在Shell脚本中,\033[XXm 是 ANSI转义序列,用于控制终端文本的颜色和样式。以下是完整的颜色和样式代码列表: 1. 基本格式 echo -e "\033[CODEm你的文本\033[0m"\033[:转义序列开始(\e[ 或 \x1b[ 等效&#…...
模型加载常见问题
safetensors_rust.SafetensorError: Error while deserializing header: HeaderTooLarge 问题代码: model AutoModelForVision2Seq.from_pretrained( "/data-nvme/yang/Qwen2.5-VL-32B-Instruct", trust_remote_codeTrue, torch_dtypetorc…...
HCIA-Access V2.5_16_3_数据业务维护
查询ONT上的业务配置 查询ONU上的业务配置 查询OLT上网业务 查询上网业务流量 查询上网业务相关MAC地址 删除故障ONT 删除故障ONU...
Java设计开发商城抢票功能
在开发一个商城抢购功能时,需要考虑几个关键方面,包括并发控制、数据一致性、用户体验以及系统的可扩展性。下面我将通过一个简单的步骤指南来介绍如何设计这样一个功能。 1. 需求分析 首先,明确抢购功能的需求: 限制购买数量。…...
【APM】Build an environment for Traces, Metrics and Logs of App by OpenTelemetry
系列文章目录 此系列文章介绍如何搭建Observability(可观测性)环境(Opentelemetry-Collector、Tempo、Prometheus、Loki和Grafana),以及应用。 【APM】Observability Solution 【APM】Build an environment for Traces, Metrics and Logs …...
全自动驾驶(FSD,Full Self-Driving)自动驾驶热点技术的成熟之处就是能判断道路修复修路,能自动利用类似“人眼”的摄像头进行驾驶!值得学习!
全自动驾驶(FSD,Full Self-Driving)软件是自动驾驶领域中的热点技术,其核心目标是实现车辆在各种复杂交通环境下的安全、稳定、高效自动驾驶。FSD软件的技术核心涉及多个方面的交叉技术,下面将详细分析说明其主要核心技…...
需要处理哪些响应数据?
在调用淘宝商品搜索 API 时,响应数据通常是一个 JSON 对象,包含了搜索结果的详细信息。以下是需要处理的主要响应数据字段及其说明: 响应数据结构 示例 JSON 数据 JSON {"code": "0","errorMessage": &quo…...