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

高并发内存池(四):内存释放原理与实现

        前言:经过前3期的攻坚,我们已完整实现了内存动态申请的核心模块。接下来将进入关键阶段——内存释放机制的理解与实现,这是构建完整 高并发内存池 的最后一块技术拼图。该模块完成后,项目主体架构将基本成型(达90%),后续主要聚焦于边界测试和性能调优。欢迎关注本专栏的开发者们持续追踪代码演进,共同探讨高并发内存池的工程实践优化方案。

项目专栏:高并发内存池_敲上瘾的博客-CSDN博客

个人主页:敲上瘾-CSDN博客

目录

​编辑

一、ThreadCache内存释放

二、CentralCache内存回收

三、PageCache内存回收

四、源码


一、ThreadCache内存释放

        在ThreadCache层我们探讨过这样一个问题,某一时段某个线程可能需要大量内存,不断向span桶中申请。而用完后这些内存就被放回它自己的自由链表桶了,导致后续线程再需要向span桶申请内存时资源不足,大部分内存都堆积在这个线程自由链表桶

        为了解决这样的问题,我们需要将部分内存归还给CentralCache。那么,自由链表达到多长时需要放回span桶呢?

        之前在设计应该从span桶取多少内存块比较合适时我们也有过类似的困扰,当时设计了一个慢增长算法,每个自由链表中存了一个_maxSize,这里我们就做简单一点,用_maxSize来判断,即当一个自由链表长度超过一个批量(_maxSize)应该申请的内存时,我们把自由链表的_maxSize个节点还回span桶

首先在class ThreadCache中声明一个函数,用来把要释放的内存截下来送入CentralCache层。

        作用是把list中自由链表的_maxSize个节点截下来,然后送入CentralCache层,因为需要找到对应的哈希桶,所以传入内存块大小。

然后在Deallocate函数(释放内存)中检查是否满足归还span桶的条件,如下:

void ThreadCache::Deallocate(void* obj, size_t bytes)
{int index = SizeClass::Index(bytes);_freelists[index].Push(obj);if (_freelists[index].Size() >= _freelists[index].MaxSize()){size_t size = SizeClass::RoundUp(bytes);ListTooLong(_freelists[index], size);}
}

注:Size用来获取链表长度,这里就不展示了,可以用这两种方法之一:

  • 直接遍历链表并计数。
  • 添加并维护_size成员函数,Size()中直接返回_size。 

因为每次使用Size函数都遍历链表会影响效率,所以这里选用添加_size成员的方法。

接下来实现ListTooLong函数:

void ThreadCache::ListTooLong(FreeList& list, size_t size)
{void* start = nullptr;void* end = nullptr;list.PopRange(start, end, list.MaxSize());//交给CentralCacheCentralCache::GetInstance()->ReleaseListToSpans(start, size);
}

        同样的使用start和end指针去取内存,在class FreeList里封装一个函数PopRange,如果你看懂了之前内存申请的代码,这里的实现就显得很简单,不在一一讲解。代码示例:

//取一段内存
void PopRange(void* start, void* end, int num)
{assert(num <= _size);start = end = _list_head;for (int i = 0; i < num - 1; i++){end = Nextobj(end);}_list_head = Nextobj(end);Nextobj(end) = nullptr;_size -= num;
}

二、CentralCache内存回收

小节目标:ReleaseListToSpans(start, size)的实现

        CentralCache内存回收的主要任务就是把ThreadCache送来的内存连接到span桶中,其次,同样的问题,什么时候送到下一层呢?这个问题我们探讨过,就是span中的所有内存块都回收回来时

        记住:理解为什么要span中的所有内存块回收回来后送入下一层这一点很重要,在下文会讲到。

回收的内存插入到Span的自由链表中

        现在有一个问题:内存块要插入到哪个span?我们知道的size仅能找到它所在的哈希桶,也就是一个span链,要具体到某个span节点是一个很让人头疼的问题。

注意:不能粗鲁地把内存块连接到一个随便找的span,这样的话,属于不同页的内存块就混乱在一起,后面的PageCache就没法玩了!

        追溯到本质(思考内存块从“出生”到现在的这个过程):内存块连接到某个span,实际上是要找到内存块属于那个页号,然后连接到这个页号对应的span中。

        页号成为了它们之间的脐带,内存块地址除以8KB就是它所在的页,而一个span的信息中也能找到它管理着哪些页,只需要做一个页号到span的映射(即哈希表)就能解决问题。页级别的内存管理是在PageCache,我们把哈希映射在PageCache层创建和维护。

在PageCache中添加成员:

  • unordered_map<PAGE_ID, Span*> _idSpanMap;  

        _idSpanMap在哪里填写呢?答:在页分配时。在向系统申请内存和给span分配页前是不能确定页号和span的对应关系的,所以哈希映射是随程序运行的动态填写过程。

        将要被连接到CentralCache层的span,需要把它管理的所有页都映射到span中,因为拆开的内存块能获取到的是一个确定的页号。放回PageCache的span只需要它管理的开始页号和尾页号映射到span,用于span合并时对相邻页的查找。

如下:

Span* PageCache::NewSpan(size_t k)
{assert(k > 0 && k < NPAGES);if (!_spanLists[k].Empty()){return _spanLists[k].PopFront();}for (int i = k + 1; i < NPAGES; i++){//切割页(即页分配)if (!_spanLists[i].Empty()){Span* nSpan = _spanLists[i].PopFront();Span* kSpan = new Span;kSpan->_n = k;//页数nSpan->_n -= k;//填写页号kSpan->_pageId = nSpan->_pageId;nSpan->_pageId += k;//建立映射_idSpanMap[nSpan->_pageId] = nSpan;_idSpanMap[nSpan->_pageId + nSpan->_n - 1] = nSpan;for (PAGE_ID i = 0; i < kSpan->_n; i++){_idSpanMap[kSpan->_pageId + i] = kSpan;}_spanLists[nSpan->_n].PushFront(nSpan);kSpan->_isUse = true;//表示span被CentralCache使用,在下文会讲到。return kSpan;}}//向系统申请内存Span* span = new Span;void* ptr = SystemAlloc(NPAGES - 1);span->_pageId = (PAGE_ID)ptr>>PAGE_SHIFT;span->_n = NPAGES - 1;_spanLists[span->_n].PushFront(span);return NewSpan(k);
}

对于使用内存块查找span我们封装一个函数,如:

Span* PageCache::MapObjectToSpan(void* obj)
{PAGE_ID index = (PAGE_ID)obj >> PAGE_SHIFT;auto ret = _idSpanMap.find(index);if (ret == _idSpanMap.end()){assert(false);return nullptr;}else{return ret->second;}
}

接下来我们来实现ReleaseListToSpans(start, size),它的核心工作:

  1. 找到每个内存块对应的span。
  2. 把内存块连接到span的自由链表中。
  3. 判断内存块是否全部回收,如果是,就将span送入PageCache中。

注意:找到哈希桶后需要加桶锁。

        对于第3点,在把span送入PageCache之前,需要把span从CentralCache移除,并把span前后指针指向空,自由链表指向空。其次走到这一步意味着程序将离开CentralCache层进入PageCache层,在此之前把桶锁解了,方便让其他线程使用,然后加锁执行PageCache的内存回收函数,解锁,然后再次申请桶锁

代码示例:

void CentralCache::ReleaseListToSpans(void* start, size_t size)
{void* p  = start;//找到每个p所在Span并连接到自由链表//加桶锁int index = SizeClass::Index(size);_spanLists[index]._mtx.lock();while (p){void* next = Nextobj(p);Span* span = PageCache::GetInstance()->MapObjectToSpan(p);Nextobj(p) = span->_freeList;span->_freeList = p;span->_useCount--;if (span->_useCount == 0){//移出Span链表_spanLists->Erase(span);span->_freeList = nullptr;span->_next = span->_prev = nullptr;//交给PageCache回收_spanLists[index]._mtx.unlock();PageCache::GetInstance()->_pageMtx.lock();PageCache::GetInstance()->ReleaseSpanToPageCache(span);PageCache::GetInstance()->_pageMtx.unlock();_spanLists[index]._mtx.lock();}p = next;}_spanLists[index]._mtx.unlock();
}

内存块全部回收后送入PageCache的作用:

        内存块回收到span后,它在自由链表中的排布已经不像初次从PageCache取出那样是有序的,而是混乱的。等span全部内存块回收后,就可以把它们看做一个整体,尽管内存块的排布是混乱的也没关系,这只是逻辑上的混乱,回到PageCache层后它就是一个大块页。等PageCache再次分页时,内存块次序恢复和虚拟地址一样,增加高速缓存命中率。

三、PageCache内存回收

小节目标:ReleaseSpanToPageCache(span)的实现。

        当PageCache拿到span后不要直接连接到哈希桶里,而把它前后能合并的页都合并在一起组成一个大块的页,然后再连接到哈希桶,这样可以缓解内存外碎片

        注意 是把它前后的页span合并在一起,只有连续页的span才能合并,而不是前后桶的span,前后页的span也无法依据桶来找,要找到管理它前后页的span需要用哈希映射。

        但又会带来一些问题,哈希映射得到的span可能是在CentralCache中,也有可能是在PageCache中,因为我们用的是同一个哈希映射,而合并span,指的是PageCache中的span,要如何解决?

        这里我们选择在span中添加成员变量_isUse来判断span是否分配给了CentralCache,这样就可以把它们区分开。先暂时这样写,后期再做优化。比如一个span的_isUse初始状态为false,分配给CentralCache后设为true,PageCache的回收处理后设为false。

合并条件:

  • 它相邻的页在哈希映射中。
  • 该页不被_CentralCache使用。
  • 两个span的页数相加不超过128。

合并过程:

  • 用来储存合并后结果的span:页号更新为两个span中较小的页号,页数更新为两者的页数和。
  • 另一个span:从PageCache的哈希桶中移除,delete删除,释放空间。

合并结果处理:

  • 按上面逻辑把前后页合并得到的span,_isUse设为false,将其连接到PageCache的哈希桶,然后做页到span的哈希映射。

代码示例:

void PageCache::ReleaseSpanToPageCache(Span* span)
{PAGE_ID n = span->_pageId;//向前合并while (true){PAGE_ID prev = span->_pageId - 1;auto ret = _idSpanMap.find(prev);if (ret != _idSpanMap.end()&&!ret->second->_isUse){if (span->_n + ret->second->_n >= NPAGES)break;span->_pageId = ret->second->_pageId;span->_n += ret->second->_n;_spanLists->Erase(ret->second);delete ret->second;}else break;}//向后合并while (true){PAGE_ID prev = span->_pageId + 1;auto ret = _idSpanMap.find(prev);if (ret != _idSpanMap.end() && !ret->second->_isUse){if (span->_n + ret->second->_n >= NPAGES)break;span->_n += ret->second->_n;_spanLists->Erase(ret->second);delete ret->second;}else break;}span->_isUse = false;_spanLists->PushFront(span);_idSpanMap[span->_pageId] = span;_idSpanMap[span->_pageId + span->_n - 1] = span;
}

四、源码

需要源码的小伙伴到我的gitee上取:

内存释放/PageCache · 敲上瘾/ConcurrentMemoryPool - 码云 - 开源中国

非常感谢您能耐心读完这篇文章。倘若您从中有所收获,还望多多支持呀!74c0781738354c71be3d62e05688fecc.png

相关文章:

高并发内存池(四):内存释放原理与实现

前言&#xff1a;经过前3期的攻坚&#xff0c;我们已完整实现了内存动态申请的核心模块。接下来将进入关键阶段——内存释放机制的理解与实现&#xff0c;这是构建完整 高并发内存池 的最后一块技术拼图。该模块完成后&#xff0c;项目主体架构将基本成型&#xff08;达90%&…...

【正点原子STM32MP257连载】第四章 ATK-DLMP257B功能测试——EEPROM、SPI FLASH测试 #AT24C64 #W25Q128

1&#xff09;实验平台&#xff1a;正点原子ATK-DLMP257B开发板 2&#xff09;浏览产品&#xff1a;https://www.alientek.com/Product_Details/135.html 3&#xff09;全套实验源码手册视频下载&#xff1a;正点原子资料下载中心 文章目录 第四章 ATK-DLMP257B功能测试——EEP…...

《突破控件限制:用Qt绘图API解锁高级界面定制能力》

一、基本概念 虽然 Qt 已经内置了很多的控件&#xff0c;但是不能保证现有控件就可以应对所有场景。很多时候我们需要更强的 “自定制” 能力。 Qt 提供了画图相关的 API&#xff0c;允许我们在窗口上绘制任意的图形形状来完成更复杂的界面设计 所谓的 “控件” 本质上也是通…...

MyBatis-Plus 中BaseMapper接口是如何加速微服务内部开发的?

假设我们有一个简单的微服务项目&#xff0c;需要对 User 实体进行基本的数据库操作。 场景一&#xff1a;使用原生 MyBatis 的开发流程 (作为对比) 定义实体类 (Entity): // package com.yourcompany.usermicroservice.entity; public class User {private Long id;private S…...

AIGC-十款数据分析类智能体完整指令直接用(DeepSeek,豆包,千问,Kimi,GPT)

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列AIGC(GPT、DeepSeek、豆包、千问、Kimi)👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资…...

鸿蒙应用(医院陪诊系统)开发篇1·主页面的tabs布局

引言&#xff1a; 首先可在鸿蒙开发者官网找到DevEco Studio的安装教程。 安装好了之后&#xff0c;我们开始开发。 知识点&#xff1a; tabs布局&#xff0c;鸿蒙官方文档地址&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-contai…...

【大模型】DeepSeek + Coze 打造个人专属AI智能体使用详解

目录 一、前言 二、AI智能体介绍 2.1 什么是AI智能体 2.2 AI智能体核心能力 2.3 AI智能应用场景 三、coze 介绍 3.1 coze是什么 3.1.1 平台概述 3.1.2 平台适用人群 3.2 平台核心功能 3.3 coze可以做什么 3.4 为什么选择coze 四、coze 搭建AI智能体操作实践 4.1 搭…...

7.(vue3.x+vite)弹性布局(flex布局)

1:效果截图 2:代码实现 <template><span style="font-size: 20px">右边固定,左边自适应</span><div class=<...

Python基础总结(五)之字典

文章目录 一、字典的格式二、字典的操作2.1 增加项2.1.1 直接增加项2.1.1 formkeys方法 2.2 删除项2.2.1 clear()方法2.2.2 pop()方法 2.3 修改项2.3.1 直接修改2.3.2 update()方法 2.4 查找项2.4.1 get()方法2.4.2 直接查询2.4.3 items()方法2.4.4 keys()方法2.4.5 values()方…...

MCP简介:重构人机交互底层逻辑

在人工智能技术飞速发展的今天&#xff0c;大语言模型&#xff08;LLM&#xff09;的应用场景正不断拓展&#xff0c;但模型与外部系统之间的连接方式却成为制约其潜力发挥的关键瓶颈。为了解决这一难题&#xff0c;由AI领域顶尖公司Anthropic&#xff08;Claude模型背后的开发…...

LangChain缓存嵌入技术完全指南:CacheBackedEmbedding原理与实践(附代码示例)

一、嵌入缓存技术背景与应用场景 1.1 为什么需要嵌入缓存&#xff1f; 算力消耗问题&#xff1a;现代嵌入模型&#xff08;如text-embedding-3-small&#xff09;单次推理需要约0.5-1秒/文本 资源浪费现状&#xff1a;实际业务中约30%-60%的文本存在重复计算 成本压力&#…...

国产DPU芯片+防火墙,能否引领网络安全新跨越?

近日&#xff0c;国内首款搭载国产DPU芯片的800Gbps下一代防火墙——中科网威NSFW - 12000正式发布&#xff0c;引发行业广泛关注。 国产DPU芯片与防火墙的结合&#xff0c;正在推动网络安全领域实现技术突破与体系升级。以下从技术特性、应用场景和产业价值三个维度分析其引领…...

Spark-SQL与Hive的连接及数据处理全解析

Spark-SQL与Hive的连接及数据处理全解析 在大数据处理领域&#xff0c;Spark-SQL和Hive都是重要的工具。今天就来聊聊Spark-SQL如何连接Hive以及相关的数据处理操作。 Spark-SQL连接Hive有多种方式。内嵌Hive虽然使用简单&#xff0c;直接就能用&#xff0c;但在实际生产中…...

ArcGIS Desktop使用入门(四)——9版本与10版本区别

系列文章目录 ArcGIS Desktop使用入门&#xff08;一&#xff09;软件初认识 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——标准工具 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——编辑器 ArcGIS Desktop使用入门&#xff08;二&#x…...

使用 chromedriver 实现网络爬虫【手抄】

1、引用 selenium 包 <dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.29.0</version> </dependency> <dependency><groupId>org.seleniumhq.seleniu…...

ERROR: Unknown host CPU architecture: arm64

1、先检查NDK版本是否支持arm64&#xff0c;NDK版本21.3以上 2、检查gradle中&#xff0c;有关NDK版本是否设置arm64-v8a 例如&#xff1a; ndkVersion "21.4.7075529"ndk {abiFilters "armeabi-v7a","arm64-v8a"} local.properties中&#x…...

从 SQL2API 到 Text2API:开启数据应用开发的新征程

在技术革新浪潮的席卷下&#xff0c;数据应用开发领域正经历着深刻变革。曾经&#xff0c;构建数据 API 需要开发者具备扎实的数据库知识和编程技能&#xff0c;手动编写复杂的 SQL 查询与 API 代码&#xff0c;这一过程不仅耗时费力&#xff0c;还将众多非技术人员阻挡在数据应…...

OpenCv高阶(四)——角点检测

一、角点检测 在计算机视觉中&#xff0c;角点检测是识别图像中局部区域&#xff08;角点&#xff09;的关键技术&#xff0c;这些区域通常是两条或多条边缘的交点&#xff0c;具有丰富的结构信息&#xff0c;常用于图像匹配、跟踪、三维重建等任务。 Harris角点检测算法是一…...

centos8 部署 openstack

在 CentOS 8 上部署 OpenStack 是一个复杂的过程&#xff0c;涉及多个组件的安装和配置。OpenStack 是一个开源的云计算平台&#xff0c;它提供了基础设施即服务&#xff08;IaaS&#xff09;的功能。下面我将指导你通过基本的步骤来部署 OpenStack。 前提条件 系统要求&#…...

智能云图库-8-AI编辑

一、基础图片编辑​ 需求分析​ 在日常的图片管理中&#xff0c;用户经常需要对图片进行简单处理&#xff0c;比如裁剪多余部分、旋转图片、放大缩小尺寸等。 因此&#xff0c;我们首先要引入基础图片编辑功能&#xff0c;帮助用户快速完成以下操作&#xff1a; 裁剪&#…...

libwebsocket建立服务器需要编写LWS_CALLBACK_ADD_HEADERS事件处理

最近在使用libwebsocket&#xff0c;感觉它搭建Http与websocket服务器比较简单&#xff0c;不像poco库那么庞大&#xff0c;但当我使用它建立websocket服务器后&#xff0c;发现websocket客户端连接一直没有连接成功&#xff0c;不知道什么原因&#xff0c;经过一天的调试&…...

L1-002 打印沙漏

L1-002 打印沙漏 - 团体程序设计天梯赛-练习集 (pintia.cn) 本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”&#xff0c;要求按下列格式打印 ************ *****所谓“沙漏形状”&#xff0c;是指每行输出奇数个符号&#xff1b;各行符号中心对齐&#…...

JSP技术入门指南【一】利用IDEA从零开始搭建你的第一个JSP系统

Jsp技术入门指南【一】利用IDEA从零开始搭建你的第一个JSP系统 前言一、什么是JSP1.1 JSP是干什么的&#xff1f;1.2 JSP与Servlet的关系是什么&#xff1f; 二、在Idea中创建第一个JSP系统三、JSP和HTML的差别3.1 格式区别3.2 注释区别 前言 在前面的内容中&#xff0c;我们已…...

NLP高频面试题(四十四)——RLHF过程中的马尔科夫决策过程及对话场景MDP设计

什么是马尔科夫决策过程(MDP)? 马尔科夫决策过程(MDP)是描述序贯决策问题的数学框架,由五元组( (S, A, P, R, \gamma) )组成,其中: (S):状态集合,描述环境的所有可能状态。(A):动作集合,描述智能体可以采取的所有可能动作。(P):状态转移概率函数,表示从一个状态…...

青少年编程与数学 02-016 Python数据结构与算法 24课题、密码学算法

青少年编程与数学 02-016 Python数据结构与算法 24课题、密码学算法 课题摘要:一、对称加密算法AES&#xff08;高级加密标准&#xff09;DES&#xff08;数据加密标准&#xff09;3DES&#xff08;三重数据加密标准&#xff09; 二、非对称加密算法RSAECC&#xff08;椭圆曲线…...

艺术字体AI生成阿里云WordArt锦书、通义万相、SiliconFlow、Pillow+OpenCV本地生成艺术字体

基于您的需求&#xff0c;结合最新API技术和搜索结果&#xff0c;以下是Python调用主流艺术字API的代码案例及对应充值链接方案&#xff1a; 一、大厂API服务&#xff08;付费方案&#xff09; 1. 阿里云WordArt锦书API # 文字纹理生成&#xff08;需安装dashscope&#xff…...

GIS开发笔记(7)结合osg及osgEarth实现不同高度下的三个圆形区域形成的三维覆盖轮廓区域绘制

一、实现效果如下&#xff1a; 二、实现原理 输入四个坐标点&#xff0c;第一个点为中心点&#xff0c;第二三四个点分别以中心点与地面垂线所在线上的各自高度水平面的交点为圆心旋转360进行圆形区域绘制&#xff0c;然后将三个不同高度上的圆形区域进行结合形成三维覆盖区域…...

解决 Kubernetes 调度器启动报错:缺少 Bind 插件

解决 Kubernetes 调度器启动报错&#xff1a;缺少 Bind 插件 问题描述 在启动自定义 Kubernetes 调度器时&#xff0c;出现了以下错误&#xff1a; I0416 17:08:41.420188 68788 configfile.go:57] "KubeSchedulerConfiguration v1beta2 is deprecated in v1.25, wil…...

Spring Batch 专题系列(六):并行处理与性能优化

1. 引言 在上一篇文章中,我们学习了 Spring Batch 的错误处理机制(Skip、Retry、Restart 和 Listener),掌握了如何提升作业的健壮性。随着数据量的增加,批处理任务的性能成为关键挑战。Spring Batch 提供了强大的并行处理功能,包括多线程 Step、分区(Partitioning)和并…...

WPF 从Main()方法启动

1.去掉App.xaml StartupUri“MainWindow.xaml” 只会让App.g.cs 不生成这行代码&#xff0c;但是还是会生成的App.g.cs文件中生成Main方法 this.StartupUri new System.Uri("MainWindow.xaml", System.UriKind.Relative);默认的App.xaml的生成操作是 应用程序定义…...

记录小程序第一次调用Api,基于腾讯云Serverless函数,实现小程序的成功接入api,以及数据调用

目录 创建腾讯云个人账户新建severless应用建立函数URL小程序中调用api示例 创建腾讯云个人账户 百度搜索即可&#xff0c;并注册 新建severless应用 作者以github下载的某Api为例&#xff0c;这里不展示具体Api&#xff0c;只关注操作即可&#xff0c;相信都是互通的 在腾…...

「数据可视化 D3系列」入门第四章:DOM操作与元素管理

DOM操作与元素管理 核心技能&#xff1a;元素选择与操作一、元素选择&#xff1a;精准定位DOM节点基础选择方法对比进阶选择技巧 二、元素插入&#xff1a;动态构建DOM结构append() vs insert()实际应用示例 三、元素删除&#xff1a;优雅移除DOM节点删除操作最佳实践 四、内容…...

突发重磅消息!!!CVE项目将被取消?

突发重磅消息&#xff01;&#xff01;&#xff01;CVE项目将被取消&#xff1f;突发&#xff01;来自可靠消息来源。MITRE 对 CVE 项目的支持将于明天到期。附件信件已发送给 CVE 董事会成员。https://mp.weixin.qq.com/s/N3qkiHaDfzDuBMK3JbBCjw...

基于uniapp的鸿蒙APP大数据量性能优化

文章目录 一、问题诊断与性能瓶颈分析1.1 大数据场景下的典型性能问题1.2 性能监测工具使用1.2.1 HBuilderX内置分析器1.2.2 鸿蒙DevEco工具链1.2.3 自制性能埋点 二、数据加载优化方案2.1 分页加载实现&#xff08;带错误重试机制&#xff09;2.2 数据流优化策略2.2.1 数据压缩…...

【算法】归并排序

算法系列七&#xff1a;归并排序 一、归并排序的递归探寻 1.思路 2.搭建 2.1设计过掉不符情况&#xff08;在最底层时&#xff09; 2.2查验能实现基础排序&#xff08;在最底层往上点时&#xff09; 2.3跳转结果继续往上回搭 3.实质 4.实现 二、递归的调用栈 1.递归的…...

【JavaScript】二十三、M端事件 + 轮播图Swiper插件

文章目录 1、M端事件2、swiper插件2.1 插件2.2 轮播图插件Swiper的使用 3、案例&#xff1a;学生信息表 1、M端事件 移动端有一个独有的事件&#xff1a;触屏事件 touch(也称触摸事件)&#xff0c;Android 和 IOS 都有&#xff0c;touch 对象代表一个触摸点。触摸点可能是一根…...

【Spring】DI(依赖注入)详解:属性注入@Autowired(超详细)、构造方法注入、Setter注入

1.DI&#xff08;依赖注入&#xff09;介绍 1.1DI是什么&#xff1f; DI&#xff08;Dependency Injection&#xff0c;依赖注入&#xff09; 是 Spring 框架中实现 IoC&#xff08;控制反转&#xff09;的一种核心机制。如果说 IoC 是一种设计思想&#xff0c;告诉我们“把控…...

Spring Boot 中配置 Redis 连接池的详细

目录 一、添加依赖二、配置 Redis 连接池&#xff08;一&#xff09;通过 Java 配置类&#xff08;二&#xff09;通过 application.properties 文件 三、测试 Redis 操作四、总结 一、添加依赖 在 pom.xml 文件中添加以下依赖&#xff1a; <dependencies><dependen…...

系统架构设计师:系统架构概述案例分析与简答题、详细解析与评分要点

10道系统架构概述知识体系案例分析与简答题&#xff0c;涵盖架构设计原则、质量属性、演化过程、评估方法等核心考点&#xff0c;并附详细解析与评分要点&#xff1a; 一、案例分析题&#xff08;5题&#xff09; 1. 电商系统高并发场景下的架构设计 背景&#xff1a;某电商平…...

关于系统架构思考,如何设计实现系统的高可用?

绪论、系统高可用的必要性 系统高可用为了保持业务连续性保障&#xff0c;以及停机成本量化&#xff0c;比如在以前的双十一当天如果出现宕机&#xff0c;那将会损失多少钱&#xff1f;比如最近几年Amazon 2021年30分钟宕机损失$5.6M。当然也有成功的案例&#xff0c;比如异地…...

阿里云短信服务与ASP.NET对接实例

准备工作 注册阿里云账号并开通阿里大于(现称"阿里云短信服务")服务 获取AccessKey ID和AccessKey Secret 申请短信签名和短信模板并审核通过 ASP.NET Web项目集成步骤 1. 安装阿里云SDK 通过NuGet包管理器安装阿里云短信服务SDK&#xff1a; Install-Package…...

【含文档+PPT+源码】基于微信小程序健康管理之健身房管理系统的设计与实现

课程目标&#xff1a; 教你从零开始部署运行项目&#xff0c;学习环境搭建、项目导入及部署&#xff0c;含项目源码、文档、数据库、软件等资料 课程简介&#xff1a; 本课程演示的是一款基于微信小程序健康管理之健身房管理系统的设计与实现&#xff0c;主要针对计算机相关…...

微信小程序转为App实践篇 FinClip

参考下面链接先 开始实践 微信小程序转为App并上架应用市场_微信小程序生成app-CSDN博客 首先在FinClip 官网上下载应用 小程序开发工具下载_小程序sdk下载资源-FinClip资源下载|泰坪小程序开放平台 下载到本地安装 打开导入自己的小程序项目&#xff1b;导入时会解析自己的…...

Qt/C++学习系列之QTreeWidget的简单使用记录

Qt/C学习系列之QTreeWidget的简单使用记录 前言1布局1.1布局要求1.2布局代码 2代码设计2.1整体勾选2.2勾选项确认 总结 前言 自己练手的项目中&#xff0c;需要对多个不同层级的选项进行勾选操作&#xff0c;而想到简洁点的操作方式就是使用QTreeWidget进行布局与应用。这里简…...

标易行项目redis内存中放哪些数据

结合你的项目经验,以下是 标易行投标服务平台 中 Redis 内存存储的核心数据类型及具体应用场景分析: 1. 用户订阅配置与实时推送 场景需求:用户订阅招标商机后,系统需实时推送符合订阅条件(如行业、区域、关键词)的标讯。Redis 存储数据: 订阅规则缓存:以 Hash 存储用户…...

redis 放置序列化的对象,如果修改对象,需要修改版本号吗?

在 Redis 中存储序列化对象时,如果修改了对象的类结构(例如增删字段、修改字段类型或顺序),是否需要修改版本号取决于序列化协议的兼容性策略和业务场景的容错需求。以下是详细分析: 1. 为什么需要考虑版本号? 序列化兼容性问题: 当对象的类结构发生变化时,旧版本的序列…...

MySQL——流程控制

一、IF条件语句 语法 IF condition THENstatements; ELSEIF condition THENstatements; ELSEstatements; END IF; 判断成绩等级 # 判断成绩等级 # 输入学生的编号,取出学生的第一门课&#xff0c;然后判断当前的课程的等级 drop procedure if exists p2; delimiter $$ crea…...

蓝桥杯 1.路径之谜

1.路径之谜 原题目链接 问题描述 小明冒充 X 星球 的骑士&#xff0c;进入了一个奇怪的城堡。城堡里边什么都没有&#xff0c;只有方形石头铺成的地面。假设城堡的地面是 n n 的方格&#xff0c;如下图所示&#xff1a; 骑士要从西北角走到东南角。可以横向或纵向移动&…...

学习笔记十二——Rust 高阶函数彻底入门(超详细过程解析 + 每步数值追踪)

&#x1f4a1; 彻底搞懂 Rust 高阶函数&#xff01;新手最容易卡住的语法 调用流程全讲透&#xff08;含逐步拆解&#xff09; Rust 函数式编程中有一个常见却经常让人懵的概念&#xff1a;高阶函数&#xff08;Higher-Order Function&#xff09; 一看到 fn(i32) -> i32、…...

Spring Cache(笔记)

简介&#xff1a; 常用注解&#xff1a;...