6.3 内存池模式

Bruce Powel Douglass大师介绍-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/ChatCoding/article/details/134665868嵌入式软件开发从小工到专家-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/ChatCoding/article/details/135297955C嵌入式编程设计模式源码-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/ChatCoding/article/details/134819019

静态分配模式是一种内存管理策略,仅适用于系统本质上静态的系统。

内存池模式也是一种内存管理策略,它在系统启动时预先分配一定数量的对象,并在需要时提供给客户端使用。这种模式既避免了动态分配的非确定性和碎片化,又提供了静态分配的灵活性,适用于需要在运行期间分配和回收大量相似对象的系统。

6.3.1 Abstract

许多应用程序中,大量的客户端可能需要创建对象,例如数据对象或消息对象。这些对象的需求往往难以预测。这时,预先创建对象池就很有意义(此时,没必要初始化对象)。客户端可根据需要获取对象,用完后归还池中。

6.3.2 Problem

内存池模式适用于以下系统

  • 系统需要频繁创建和销毁大量相似的小型对象,例如事件、消息或数据对象。
  • 系统无法承受动态内存分配带来的问题,例如内存碎片、性能开销和安全问题。
  • 系统无法预先静态分配所有对象,例如由于系统过于复杂或对象的数量无法确定。

具体来说,内存池模式可以解决以下问题

  • 内存碎片:内存池模式可以避免频繁创建和销毁对象造成的内存碎片,从而提高内存利用率。
  • 性能开销:内存池模式可以减少系统的性能开销,例如减少垃圾回收的开销。
  • 安全问题:内存池模式可以减少内存泄漏和越界访问等安全问题。

6.3.3 Pattern Structure

图 6-3 展示了内存池模式的结构。可参数化的泛型池管理器类用于创建特定类型的池化对象。系统中通常会存在多个这样的实例化池,但每个特定的池化类型只有一个。

每个池创建并管理其对象集,在需要时分配对象,并返回分配对象的引用或句柄给客户端。在释放后,对象将被放回可用对象列表。

6.3.4 Collaboration Roles

客户端(Client)

在嵌入式系统中,任何需要使用resourceClass类的对象都是客户端。客户端通过调用ResourcePool::allocate()向池请求对象,并在使用完成后通过ResourcePool::release()释放对象归还给池。

通用池管理器(Generic Pool Manager)

通用池管理器是一个模板类,它使用模板参数pooledClassBufferSize分别指定要池化的对象类型和数量。

内存池(PooledClass)

PooledClass 表示实例化类对象对所对应的存储空间(内存池)。它可以是任何你想要的对象,但通常情况下,它们是简单、小型的类,由各种客户端使用。例如,在嵌入式系统中,PooledClass 可以是事件、消息、数据对象等。

资源池管理器(Resource Pool Manager)

资源池管理器类是已实例化的通用池管理器,系统中可以有多个这样的实例,但每个特定资源类最多只有一个实例。

模板实例化是指为模板类或模板函数指定具体的类型的过程。

6.3.5 Consequences

优点:

  • 避免动态内存分配的复杂性: 内存池模式在系统启动时一次性分配所有内存,不需要动态分配内存。这消除了动态内存分配带来的诸多问题,例如内存碎片、分配时间不确定性等,从而提高了系统的稳定性和可预测性。
  • 适用于复杂系统: 内存池模式可以处理一定程度的非确定性对象分配,因此比静态分配模式更适合复杂系统。尤其适用于以下场景:
    • 系统可能需要许多不同的客户端共享大量通用对象,但这些对象的分配数量和分布无法在设计阶段确定。
    • 系统需要在运行时根据实际需求动态分配对象。
  • 提高性能: 由于所有池化对象都在系统启动时创建,不需要动态分配内存,可以减少内存分配的操作,从而提高系统的运行效率。

缺点:

  • 对设计要求高: 内存池模式要求在设计阶段确定所有池化对象的类型和数量。如果这种决策失误,可能会导致系统在启动或运行过程中内存不足而崩溃。
  • 系统扩展受限: 内存池模式的系统难以根据新的需求进行扩展,因为池的大小在设计阶段就已确定。因此,该模式更适合于需求明确、相对稳定的嵌入式系统。

总结:

内存池模式是一种有效的内存管理模式,适用于需要频繁创建和销毁大量相似小型对象的嵌入式系统。在使用该模式时,需要注意其对设计要求高、系统扩展受限等缺点,并结合系统的实际需求进行权衡。

6.3.6 Implementation Strategies

本节提供了实现模式的策略,特别是在C++中。建议重写new和delete操作符以使用池管理器,这可以隐藏应用程序程序员不必直接处理池化与动态分配的复杂性。

内存池模式的实现相对简单。在 C++ 中,为了方便使用,通常会重写 newdelete 运算符,使其直接调用池管理器进行分配和释放操作。这样,应用程序开发人员无需关心是动态分配还是池化分配,简化了代码。

扩展与组合:

内存池模式可以与其他设计模式组合使用,例如与工厂模式([1])结合,根据需要创建特定的子类型对象。

具体实现参见《C++高级编程》

6.3.7 Related Patterns

内存池模式与其他内存管理模式的关系:

  • 静态分配模式: 适用于相对简单的嵌入式系统,所有内存分配都在系统启动时完成,不需要动态分配,优点是稳定可预测,缺点是灵活性较低。
  • 动态分配模式及其变种: 适用于更复杂的系统,允许在运行时动态分配内存,优点是更灵活适应需求变化,缺点是容易产生内存碎片降低性能,并带来内存泄漏风险。
  • 抽象工厂模式 [1] (Abstract Factory Pattern): 可以与内存池模式结合使用,在不同的运行环境中创建针对特定环境的池化对象,提高代码的可重用性和灵活性。

总结:

内存池模式是嵌入式系统中常用的内存管理技术,适用于需要频繁创建和销毁大量相似小型对象的场景。选择合适的内存管理模式需要根据系统复杂性、性能需求和灵活性等因素进行权衡,并考虑与其他模式的组合使用。

6.3.8 Sample Model

原书内容存在错误,见红色

对象模型 (图 6-4a):

图 6-4a 展示了基于图 6-3 所示模式派生出来的类模型的对象关系。系统中存在一个 TempDataPool 对象,管理着 1000 个 TempData 对象实例。图中还展示了三个 TempDataPool 的客户端:

  • TempSensor: 每半秒记录一次温度的温度传感器。每次记录温度时,TempSensor 会从池中分配一个 TempData 对象来存储温度信息。然后,它将这个对象传递给两个客户端:TempView 和 TempHistory。TempView 用于将温度显示在 GUI 界面上,TempHistory 用于维护最近几秒钟的温度历史记录。
  • TempView: 一个 GUI 对象,负责将温度值显示在用户界面上。当 TempView 显示完温度后,它会释放之前从池中分配的 TempData 对象,归还给池中。
  • TempHistory: 维护最近 10 秒钟的温度历史数据。对于前 20 个温度样本,TempHistory 不会释放接收到的 TempData 对象,而是将它们缓存起来。当收到新的温度数据时,它会释放最老的 TempData 对象,腾出空间存储新的数据。

时序图 (图 6-4b):

图 6-4b 演示了对象在运行期间的一个场景:

  1. 系统启动时,首先创建 TempDataPool 对象,并由它创建 1000 个 TempData 对象,存储在池中。
  2. TempSensor 从池中分配一个 TempData 对象,存储测得的温度值。
  3. TempSensor 将 TempData 对象分别传递给 TempView 。
  4. TempView 将温度值显示在 GUI 界面上。
  5. TempView 显示完温度后,释放 TempData 对象,将其放回池中。
  6. TempSensor 将 TempData 对象分别传递给 TempHistory。
  7. TempHistory 将 TempData 对象存储起来,维护最近 10 秒钟的温度历史记录。
  8. 对于前 20 个温度样本,TempHistory 不会释放接收到的 TempData 对象。
  9. 当收到第 21 个温度数据时,TempHistory 会释放最老的 TempData 对象,腾出空间存储新的数据。

 

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

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

相关文章

Android 基础技术——Handler

笔者希望做一个系列,整理 Android 基础技术,本章是关于 Handler 为什么一个线程对应一个Looper? 核心:通过ThreadLocal保证 Looper.prepare的时候,ThreadLocal.get如果不空报异常;否则调用ThreadLocal.set,…

2、趋势Trend (copy)

利用移动平均数和时间虚拟模型对长期变化进行建模。 文章目录 1、什么是趋势?2、移动平均图3、工程趋势4、示例 - 隧道交通1、什么是趋势? 时间序列的趋势组成部分代表了序列均值的持久、长期变化。趋势是序列中变化最慢的部分,代表了最重要的大时间尺度。在产品销售的时间…

Unity中使用Ultraleap的Slider组件

Unity中使用Ultraleap的Slider组件,实现物体在指定范围内滑动: 本节在上一节基础上进行,上一小结参考如下: Unity中使用Ultraleap的InteractionButton组件 本节工程文件如下: Unity中使用Ultraleap的Slider组件 1、在…

【Algorithms 4】算法(第4版)学习笔记 02 - 1.4 算法分析

文章目录 前言参考目录学习笔记1:科学方法2:观察举例:三数之和3:近似4:增长数量级4.1:二分查找 demo4.2:二分查找代码实现4.3:二分查找比较次数的证明(比较次数最多为lgN…

MYSQL的配置和安装

下载安装 打开官网 MYSQL官网 点击DOWNLOADS 滑到最低下点击:MYSQL Community(GPL) Downlads 点击Download Archives 点击MySQL Community Server进入网站 选择相应版本下载,这里选择的是5.7.24版本,x86 64位【按需选择】 下载解压 配置文件…

H5022B降压恒流芯片 内置MOS PWM调光 高性价比 支持48V 60V 80V 100V

内置MOSFET的100V降压恒流芯片是一种能够将高输入电压降低到稳定的输出电流的降压稳流器。以下是其基本工作原理: 输入电压检测:芯片首先检测输入电压,即来自电源的100V。这涉及使用电压检测电路,以确保输入电压在可接受范围内。…

springboot 怎么设置局域网访问

如何配置Spring Boot应用以实现局域网访问 在开发一个Spring Boot应用时,我们通常会通过localhost来访问和测试我们的应用。但是,当我们想要在局域网中分享我们的应用,供其他设备访问时,仅仅使用localhost是不够的。本文将引导你…

PyNest 一个可以搭建微服务的 Python 包

PyNest 在构建 Python API 和微服务方面崭露头角,解决了 FastAPI 中存在的关键问题,因此成为卓越的框架。凭借其模块化的架构和先进的特性,PyNest 在 2024 年及以后有望成为 Python 开发者的首选选择。 随着 Python 生态系统的不断成熟&…

关于信号处理中的测量精度与频谱细化问题及其仿真实践

说明 频谱细化问题其实很早之前就想研究并整理一下了,车载雷达中我们似乎对这个话题并不太涉及(最多只是在测角时用补0 FFT的方法),想要了解这个话题的源头是很早之前的一次面试时面试官问我:有哪些提高测量精度的方法?并进而引申…

Linux 文件IO

目录 linux下的文件分类: 文件描述符原理:(底层原理,可跳过) 虚拟文件系统: 内存中的inode与磁盘中的inode open函数 函数原型: 形参列表: 代码: close函数 er…

eNSP学习——华为交换机STP配置和选路规则

目录 原理概述 实验内容 实验目的 实验步骤 实验拓扑 实验步骤 基本配置 配置网络中的根交换机 理解根端口的选举 理解指定端口的选举(首先比较根路径开销) 原理概述 生成树协议(英语:Spanning Tree Protocol&#…

excel 选中指定区域

问题 excel 选中指定区域 详细问题 笔者有一个excel数据集,数据量较大,如何快速选中指定区域 解决方案 步骤1、 点击起始单元格 确定单元格坐标(建议直接CtrlC复制至剪贴板) 具体操作入下图所示 步骤2、 点击结束单元格 …

微信小程序|推箱子小游戏

推箱子游戏是一种经典的益智游戏,通过移动箱子将其推到指定位置,完成关卡的过程。随着小程序的发展,越来越多的人开始在手机上玩推箱子游戏。本文将介绍如何利用小程序实现推箱子游戏,并分享一些技术实现的方法。 目录 引言游戏背景介绍游戏规则及挑战技术实现步骤创建游戏…

Leetcode—1570. 两个稀疏向量的点积【中等】Plus

2024每日刷题&#xff08;一零四&#xff09; Leetcode—1570. 两个稀疏向量的点积 实现代码 class SparseVector { public:SparseVector(vector<int> &nums) {for(int i 0; i < nums.size(); i) {if(nums[i]) {indexNum[i] nums[i];}}}// Return the dotProd…

3 款最好的电脑硬盘数据迁移软件

您将从本页了解 3 款最好的 SSD硬盘数据迁移软件&#xff0c;磁盘供应商提供的软件和可靠的第三方软件。仔细阅读本文并做出您的选择。 什么是数据迁移&#xff1f; 数据迁移是将数据移动到其他计算机或存储设备的过程。在日常工作活动中&#xff0c;常见的数据迁移有三种&…

类Markdown实时绘图编辑器mermaid-live-editor

什么是 Mermaid &#xff1f; Mermaid 是一个基于文本的图表描述语言&#xff0c;它允许你使用简洁的语法来描述各种不同类型的图表和图示&#xff0c;例如流程图、时序图、甘特图等。 什么是 mermaid-live-editor &#xff1f; mermaid-live-editor 是一个基于 Javascript 的在…

springboot3-web开发

跟着尚硅谷学springboot3 0.配置application语法 表示复杂对象person Component ConfigurationProperties(prefix "person") public class Person {private String name;private Integer age;private Date birthday;private Child chlid;private List<Dog>…

实战Vue.js与MySQL:爱心商城项目开发指南

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

14.4.2 Flash读取与修改数据库中的数据

14.4.2 Flash读取与修改数据库中的数据 计数器是网站必不可少的统计工具&#xff0c;使用计数器可以使网站管理者对网站的访问情况有一个清晰的了解。如果仅仅是统计首页访问量的话&#xff0c;用文本文件来存储数据就可以了&#xff0c;但如果统计的数据量比较大的话(如文章系…

The Sandbox 专访|印尼国家足球队主教练申台龙

Q. 请简单介绍一下自己。 我是申台龙&#xff01;我目前担任印度尼西亚国家足球队主教练。我在印尼负责三支国家队的教练工作&#xff0c;分别是 A 组&#xff08;成年队&#xff09;、U-23 和 U-20。在韩国&#xff0c;我的名字是申台龙&#xff08;Shin Tae-yong&#xff09;…