6.3 内存池模式

news2024/10/7 8:25:08

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 对象,腾出空间存储新的数据。

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

根文件系统之initramfs

问题抛出: 1.系统启动时文件系统功能的实现 1.bootloader支持 1.uboot启动 ——典型的arm设备的选择。 情景1:使用initrd或initramfs,内核和根文件系统作为不同镜像时,uboot负责提供启动参数;加载根文件系统到内存…

C++ 设计模式之解释器模式

【声明】本题目来源于卡码网(卡码网KamaCoder) 【提示:如果不想看文字介绍,可以直接跳转到C编码部分】 【设计模式大纲】 【简介】 --什么是解释器模式(第22种设计模式) 解释器模式(Interpreter…

【INTEL(ALTERA)】带有浮点单元 (FPU) Nios® V/g 处理器在 英特尔® Cyclone10 GX 设备中执行不正确的浮点运算

说明 由于 英特尔 Quartus Prime Pro Edition 软件版本 23.3 存在一个问题,当使用 Nios V/g 处理器并在 英特尔 Cyclone 10 GX 设备中启用 FPU 时,浮点运算无法按预期进行。 Nios V/g 处理器 – 启用浮点单元 解决方法 请勿在 英特尔 CycloneNios 10 G…

张维迎《博弈与社会》笔记(2)导论:个体理性与社会最优:协调与合作问题

有节选,相当于按照自己的方式将内容组织了下吧? 协调与合作问题 什么是一个社会面临的基本问题? 这似乎是一个我们每一个人都可以触摸得到但又难以说清的问题,因为在不同的语境下,“社会”一词的内涵有所差异。但其基…

火山引擎ByteHouse:分析型数据库如何设计并发控制?

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 分析型数据库设计并发控制的主要原因是为了确保数据的完整性和一致性,同时提高数据库的吞吐量和响应速度。并发控制可以防止多个事务同时对同一数据进行…

ICMPv6报文解析及NAT处理

ICMPv6报文概述 参考RFC4443和RFC2460 ICMPv6报文是IPv6在internal control management protocol(ICMP)的基础之上做了一些改动,得到了ICMPv6协议,IPv6的next_header为58。 Message general format 每条ICMPv6消息之前都有一个…

从零开始的OpenGL光栅化渲染器构建6-PBR光照模型

前言 PBR,或者基于物理的渲染(Physically Based Rendering),它指的是一些在不同程度上都基于与现实世界的物理原理更相符的基本理论所构成的渲染技术的集合。正因为基于物理的渲染目的便是为了使用一种更符合物理学规律的方式来模拟光线,因此…

Mybatis 源码系列:领略设计模式在 Mybatis 其中的应用

文章目录 一、Builder模式二、工厂模式三、单例模式四、代理模式五、组合模式六、模板方式模式七、适配器模式八、装饰器模式九、迭代器模式 虽然我们都知道有23种设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大…

代理IP技术在云函数中的创新应用与拓展空间

目录 前言 一、代理IP技术的基本概念和原理 二、云函数的基本原理和优势 1. 弹性伸缩 2. 省时省力 3. 按需计费 三、代理IP技术在云函数中的创新应用 1. 反爬虫技术 2. 访问安全性和隐私保护 3. 地理定位和访问控制 四、代理IP技术在云函数中的拓展空间 1. 代理IP池…

力扣hot100 跳跃游戏 贪心

Problem: 55. 跳跃游戏 文章目录 思路复杂度Code 思路 👨‍🏫 参考 挨着跳,记录最远能到达的地方 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( 1 ) O(1) O(1) Code class Solution {public boolean canJump(int[] nums)…

AI大模型专题:大模型安全与伦理研究报告2024

今天分享的是AI大模型系列深度研究报告:《AI大模型专题:大模型安全与伦理研究报告2024》。 (报告出品方:腾讯研究院) 报告共计:76页 大模型具有不同于传统模型的特点和优势 第一,大模型和传统…

页面通过Vue进行整体页面不同语言切换 i18n库

目录 引入 如何做到 下载i18n库 构建整体翻译文件结构 语言包文件 i18n配置文件 把i18n挂载到vue实例上 添加按钮点击事件切换语言 引入 我们现在有这样一个要求,我们想要对我们开发的网页进行国际化操作,也就是我们不仅要有中文,还要有英文等。用户可以随时进行不同语言…

langchain+xray:prompt控制漏洞扫描

写在前面 xray是长亭推出的一款漏洞扫描工具。 langchain是调用LLM大模型完成自动化任务的框架。 本篇文章是对langchain自定义工具的探索,通过编写一个xray调用的工具,联合ChatGPT对xray进行调用,实现对目标的漏洞扫描。 xray功能分析 …

洛谷-P4124题-手机号码-Java

题目 题目链接: https://www.luogu.com.cn/problem/P4124 分析 给定两个长度为11位的数字,代表两个区间 [L,R] 需要编写程序来计算出,这两个区间内满足要求的数字个数。这样的题一般来说就是数位dp题。首先我们可以根据容斥原理 [0,R]中满…

第一批 Apple Vision Pro 开箱和佩戴体验新鲜出炉!!!

注: 本文转自微信公众号 BravoAI (专注AI资讯和技术分享), 原文网址:第一批 Apple Vision Pro 开箱和佩戴体验新鲜出炉!!!, 扫码关注公众号 编者按: 整个AR/VR行业都在等AVP, 期待它能带来ChatGPT般的冲击 AVP(Apple Vision Pro) 是苹果公司研发的第一款"空间计算 (Spa…

跟着pink老师前端入门教程-day11

3、CSS 三角 网页中常见一些三角形,使用CSS直接画出来即可,不必做成图片或字体图标 4、CSS 用户界面样式 4.1 什么是界面样式 界面样式:更改一些用户操作样式,以便提高更好的用户体验(更改用户的鼠标样式、表单轮廓…

Redis简单阐述、安装配置及远程访问

目录 一、Redis简介 1.什么是Redis 2.特点 3.优势 4.数据库对比 5.应用场景 二、 安装与配置 1.下载 2.上传解压 3.安装gcc 4.编译 5.查看安装目录 6.后端启动 7.测试 8.系统服务配置 三、Redis远程访问 1.修改访问IP地址 2.设置登录密码 3.重启Redis服务 …

《QDebug 2024年1月》

一、Qt Widgets 问题交流 1. 二、Qt Quick 问题交流 1.Repeator 的 delegate 在 remove 移除时的注意事项 Qt Bug Tracker:https://bugreports.qt.io/browse/QTBUG-47500 Repeator 在调用 remove 函数之后,对应的 Item 会立即释放,后续就…

RabbitMQ之死信队列、延迟队列和懒队列

目录 死信队列 何时会产生死信 死信队列的配置方式 参数x-dead-letter-routing-key 如何确定一个消息是不是死信 延迟队列 懒队列 声明懒队列的两种方式 参数声明 策略指定 死信队列 死信队列是RabbitMQ中非常重要的一个特性。简单理解,他是RabbitMQ对于未…

第九节HarmonyOS 常用基础组件20-Divider

1、描述 提供分割器组件,分割不同内容块或内容元素。 2、接口 Divider() 3、属性 名称 参数类型 描述 vertical boolean 使用水平分割线还是垂直分割线。 false:水平分割线 true:垂直分割线 color ResourceColor 分割线颜色 默认…