【项目日记(三)】内存池的整体框架设计

简介: 【项目日记(三)】内存池的整体框架设计

1. 前言

由于本项目是模拟学习tcmalloc

的优秀的思想以及巧妙的结构,所

以本项目只会把源项目的精华部分

拿出来学习,请大家耐心看完

本章重点:

本篇文章着重讲解本项目的大致
框架结构,以及每一层小结构的内
部的部分细节,这篇文章不会有很多
的代码演示,但至关重要!!!


2. 内存池整体结构一览

首先,我们采用了三层缓存结构来

实现不同的功能,每一层结构都互

相紧密联系:

  • ThreadCache(线程缓存结构)

线程缓存是每一个线程独享的结构,线程申请和释放内存都在这个缓存中进行,只能用于小于256KB的内存分配.整个线程缓存结构是不用加锁的

  • CentralCache(中心缓存结构)

中心缓存是所有线程所共享的,thread cache是按需从central cache中获取的对象。central cache会在合适的时机回收thread cache中的对象,避免一个线程占用了太多的内存,而其他线程的内存吃紧,达到内存分配在多个线程中更均衡的按需调度的目的。central cache是存在竞争的,所以从这里取内存对象是需要加锁,首先这里用的是桶锁,其次只有thread cache的没有内存对象时才会找central cache,所以这里竞争不会很激烈

  • PageCache(页缓存结构)

页缓存是在central cache缓存上面的一层缓存,存储的内存是以页为单位存储及分配的,central cache没有内存对象时,从page cache分配出一定数量的page,并切割成定长大小的小块内存,分配给central cache。当一个span的几个跨度页的对象都回收以后,page cache会回收central cache满足条件的span对象,并且合并相邻的页,组成更大的页,缓解内存碎片的问题

看到这儿你可能一脸懵逼,但是没关系
这里的所有内容都会在后面一一讲解

三层缓存的大致结构:


3. 线程缓存结构详解

线程缓存结构实际上是一个哈希桶,

数组的下标代表这个桶中存放的小

块内存的字节数是多少,桶中存放

小块儿内存,就是定长池中的自由链表

申请内存的步骤:

申请内存时,比如申请8字节大小内存
会先去8字节对应的哈希桶中查看有
没有小块儿内存,如果有,则直接返回
给外部,若对应的桶无小块儿内存,再去
中心缓存中拿内存!

释放内存的步骤:

释放内存时,比如释放的内存大小是16
字节,那么这块儿返回来的空间就会挂
在16字节对应的哈希桶中,当满足某种
条件时,线程缓存中的小块儿内存会还
给中心缓存(最开始的内存是中心缓存给的)


4. 中心缓存结构详解

中心缓存结构本质也是一个哈希桶,

并且它的数组下标和线程缓存是相同

的,但是哈希桶中存储的内容不同,中

心缓存中存储的是一个span结构,span

就是一个结构体,它负责管理大块内存

对span的简单介绍:

我们默认系统的一页内存是8KB,
span管理的大块儿内存实际上是
大页内存,可能是一页,两页内存,
这个大页内存会被切分为小块儿的
内存,8字节对应的哈希桶中会切分
为8字节的小块儿内存,这样可以很
方便的将小块儿内存分配给线程缓存!

span的来源与去向讲解:

中心缓存的span实际上是由页缓存分配
的,并且在一个span满足某种条件时,会
把此span还给页缓存,并且span是一个
双链表结构,一个哈希桶桶中可能有多个
span,下面是span的大致成员变量:

//管理多个连续页的大块内存跨度结构,centralcache的哈希桶中链接的就是这种结构
class SpanData
{
public:
  size_t _n = 0;//此span中的页数
  SpanData* _next = nullptr;
  SpanData* _prev = nullptr;
  size_t _useCount = 0;//span中切分好的小对象有几个被使用了
  void* _freeList = nullptr;//切分好的小块内存的自由链表
};

5. 页缓存结构详解

页缓存结构的本质也是一个哈希桶,

但它的数组下标含义与前两层不同,

它的下标代表这个哈希桶中存放的

span一共有多少页内存!

span的来源与去向讲解:

页缓存中的span和中心缓存中的
span结构体是一样的,但页缓存中的
span是直接从系统中申请的大块儿
空间,并且这个span会直接分配给中
心缓存去切分为小块儿内存后被使用

向页缓存申请span的基本步骤:

当线程缓存的哈希桶中没有小块儿内存了,并且中心缓存对应的哈希桶中页没有span了,这时会来页缓存申请span回去做切分使用,假设申请的span是5页大小,那么就会去页缓存的五号桶中查看是否有span,若有span就直接返回若没有span,则需要去6到128号桶中寻找是否存在span,假设100号桶中有span,那么会将这个100页的大span切分为一个5页的小span和一个95页的大span,再将这个5页的span返回给中心缓存,这个95页的span重新挂到页缓存的95号桶中!假如6到128号桶都没有span,则会向系统申请一个128页的大块儿空间,再来切分成小span返回!


6. 总结

这整个三层结构的设计是十分巧妙的,

在线程缓存中是不需要加锁的,因为每

个线程独享这个结构,这也是这个项目

比较快的原因之一,在中心缓存中也不

需要完全加锁,而是使用桶锁,只有当不同

的线程进入到同一个桶时才会有锁互斥!

当然这个项目的巧妙之处远不止如此
我将在后面的代码实现中,一边讲解
原理,一边带大家编码,这才能真正带大家
了解到这个项目的精髓与值得学习之处!!!

🔎 下期预告:自由链表和span结构实现🔍


相关文章
|
23天前
|
缓存 Java
《JVM由浅入深学习九】 2024-01-15》JVM由简入深学习提升分(生产项目内存飙升分析)
《JVM由浅入深学习九】 2024-01-15》JVM由简入深学习提升分(生产项目内存飙升分析)
23 0
|
10天前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
22 1
|
10天前
|
设计模式 存储 缓存
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
16 0
|
10天前
|
设计模式 安全 NoSQL
Java面试题:结合单例模式与Java内存管理,设计一个线程安全的单例类?分析Java多线程工具类ExecutorService与Java并发工具包中的工具类,设计一个Java并发框架的分布式锁实现
Java面试题:结合单例模式与Java内存管理,设计一个线程安全的单例类?分析Java多线程工具类ExecutorService与Java并发工具包中的工具类,设计一个Java并发框架的分布式锁实现
18 0
|
10天前
|
设计模式 存储 缓存
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
14 0
|
10天前
|
监控 Java
Java面试题:Java内存、多线程与并发工具包的深度探索,Java内存管理策略及其优化技巧,Java多线程并发控制的工具类与机制,Java并发工具包在实际项目中的应用
Java面试题:Java内存、多线程与并发工具包的深度探索,Java内存管理策略及其优化技巧,Java多线程并发控制的工具类与机制,Java并发工具包在实际项目中的应用
10 0
|
10天前
|
存储 算法 安全
Java面试题:给定一个可能产生内存泄漏的场景,如何诊断并解决?实现一个生产者-消费者模型,使用适当的同步机制与并发工具类,Java并发工具包与框架:性能与调优
Java面试题:给定一个可能产生内存泄漏的场景,如何诊断并解决?实现一个生产者-消费者模型,使用适当的同步机制与并发工具类,Java并发工具包与框架:性能与调优
9 0
|
10天前
|
存储 并行计算 安全
Java面试题:Java内存管理、多线程与并发框架的面试题解析与知识点梳理,深入Java内存模型与垃圾回收机制,Java多线程机制与线程安全,Java并发工具包与框架的应用
Java面试题:Java内存管理、多线程与并发框架的面试题解析与知识点梳理,深入Java内存模型与垃圾回收机制,Java多线程机制与线程安全,Java并发工具包与框架的应用
18 0
|
18天前
|
Java C++ 开发者
如何根据项目需求选择使用C++还是Python进行内存管理?
【7月更文挑战第2天】如何根据项目需求选择使用C++还是Python进行内存管理?
18 0
|
2月前
|
数据采集 人工智能 测试技术
3倍生成速度还降内存成本,超越Medusa2的高效解码框架终于来了
【5月更文挑战第21天】CLLM,一种新方法,通过并行解码提升大型语言模型推理速度3-4倍,降低内存成本,超越Medusa2。采用Jacobi解码和微调策略,保证生成质量。无需修改模型架构,训练成本低,可与现有技术集成。但依赖高质量数据集,更大数据集可提高泛化能力。[链接](https://arxiv.org/pdf/2403.00835)
41 2