memslab源码阅读总结

Memslab从结构上可以分为三层,

1最顶层是一些cache队列,

2 每个cache队列中又包含三个slab队列,

3 每个slab管理着一个页面

我们首先从这三层来介绍memslab的整体结构

1 cache队列

最顶层与cache相关的队列有

  1. Ikmem_array: 指向不同大小的cache
  2. Ikmem_lookup: 将cache按照从大到小的顺序排列组成的数组
  3. Ikmem_size_lookup1: 以4为间隔的大小(范围从4到1024),每个指向第一个大于自身大小的cache
  4. Ikmem_size_lookup2: 以1k为间隔的大小(范围从1k到256k),每个指向第一个大于自身大小的cache
  5. ikmem_large_ptr: 存放大于128k的页面

1.1 ikmem_array和ikmem_lookup数组

Memslab中用来存放cache结构的是ikmem_array数组和ikmem_lookup数组, 这两个数组被放在一块大小为2* sizelimit 大小的内存上, size_limit会随着ikmem_array的大小而变化,

在ikmem_init中,创建2^16, 2^15 … 2^3共14个cache,ikmem_array和ikmem_lookup都指向这些cache,只不过ikmem_lookup中cache是按照从大到小的顺序排列的

1.2 Ikmem_size_lookup1和Ikmem_size_lookup2数组

Ikmem_size_looup1: 以4为间隔的大小(范围从4到1024),每个指向第一个大于自身大小的cache

Ikmem_size_lookup2: 以1k为间隔的大小(范围从1k到256k),每个指向第一个大于自身大小的cache, 超过2^16的大小指向NULL

2 cache

Cache中比较重要的结构是imemlru_t array, array中会有一个entry放着刚刚被应用返回的slab中的对象,slab中的对象被返回后不会直接返回给slab,而是先放在这个数组中

以及三个slab的链表:slabs_partial, slabs_full, slabs_free, slabs_partial存放的slabs中的对象被部分分配出去,slabs_full中的对象被全部分配出去,slabs_free中的对象完全没有被分配出去

3 slab

每个slab管理着一个页面,按照obj_size将页面分为obj1, obj2 …,在未分配的时候每个对象的开头都指向下一个对象的地址,bufctl指向这个待分配链表的头部

分配算法,是一种使用单链表去管理页面空间的方式,每次分配头指针bufctl指向的页面,将bufctl指向下一个对象,对象被应用释放返回时,将对象加入链表头部,原理类似下图所示

主要的函数为ikmem_init, ikmem_malloc和ikmem_free,我们从malloc和free入手,去看一看其中的流程:

1 Ikmem_malloc:

分配时, 如果需要分配的大小小于1024, 首先在ikmem_size_lookup1中查找, 否则在ikmem_size_lookup2中寻找cache,

如果在ikmem_size_lookup1以及ikmem_size_lookup2中没有与size相同大小的cache, 就从ikmem_lookup中找到第一个比size大的cache

当所需要的size大于之前准备的2^16大小的页面, malloc一个页面, 并加入ikmem_large_ptr队列

如果在ikmem_size_lookup1或是在ikmem_size_lookup2中发现了需要的cache, 调用imemcache_alloc函数, 从这个cache中分配一个对象

1.1 Ikmem_malloc->imemcache_alloc:

程序会先去看该cache中的array有没有空余的对象, cache中的array存放着刚刚被从应用释放回来的页面, 刚释放回来的页面不会立刻放回其所属的slab, 而会放入array, 与其他刚被释放的页面形成链表, 这样的好处是避免了每次去slab中分配页面, 并且还要调整slab所属的队列,

如果array中缓存的对象为空, 就会调用imemcache_fill_batch, 从slab队列中分配batchcount个对象到array中, 然后返回这个对象

从cache中分配出去的对象的大小会被加到总的分配出去的大小ikmem_inuse上

2 ikmem_free:

首先判断, 如果分配的对象是一个在大页面的对象, 就从ikmem_large_ptr队列中删除这个对象, 并且free掉这个对象

否则的话, 调用imemcache_free去释放这个对象, 释放完后, 同样要从ikmem_inuse中减去这个释放回来的大小

2.2 Ikmem_free -> imemcache_free:

释放回来的页面会首先放到array中去,

如果array中的对象的数目超过了array->limit的大小, 程序会调用imemcache_list_free, 这个对象就会被放回slab中, 并且程序会调整slab所在的slab队列, 比如原先在slab_free中的slab, 由于对象被返回, 就会被调整到slab_partial中

如果cache中空闲的slab超过了一定数量(cache->free_limit), cache就会调用imemcache_drain_list, 去释放掉一半数量的空闲对象

时间: 2024-11-19 21:25:36

memslab源码阅读总结的相关文章

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

淘宝数据库OceanBase SQL编译器部分 源码阅读--生成逻辑计划

body, td { font-family: tahoma; font-size: 10pt; } 淘宝数据库OceanBase SQL编译器部分 源码阅读--生成逻辑计划 SQL编译解析三部曲分为:构建语法树,生成逻辑计划,指定物理执行计划.第一步骤,在我的上一篇博客淘宝数据库OceanBase SQL编译器部分 源码阅读--解析SQL语法树里做了介绍,这篇博客主要研究第二步,生成逻辑计划. 一. 什么是逻辑计划?我们已经知道,语法树就是一个树状的结构组织,每个节点代表一种类型的语法含义.如

JDK部分源码阅读与理解

本文为博主原创,允许转载,但请声明原文地址:http://www.coselding.cn/article/2016/05/31/JDK部分源码阅读与理解/ 不喜欢重复造轮子,不喜欢贴各种东西.JDK代码什么的,让整篇文章很乱...JDK源码谁都有,没什么好贴的...如果你没看过JDK源码,建议打开Eclipse边看源码边看这篇文章,看过的可以把这篇文章当成是知识点备忘录... JDK容器类中有大量的空指针.数组越界.状态异常等异常处理,这些不是重点,我们关注的应该是它的一些底层的具体实现,这篇

如何阅读Java源码 阅读java的真实体会

刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧,如果你从来没有学过Java,或是任何一门编程语言如C++,一开始去啃<Core Java>,你是很难从中吸收到营养的,特别是<深入Java虚拟机>这类书,别人觉得好,未必适合现在的你. 虽然Tomcat的源码很漂亮,但我绝不建议你一开始就读它.我文中会专门谈到这个,暂时不展开. 强烈

Memcache-Java-Client-Release源码阅读(之七)

一.主要内容 本章节的主要内容是介绍Memcache Client的Native,Old_Compat,New_Compat三个Hash算法的应用及实现. 二.准备工作 1.服务器启动192.168.0.106:11211,192.168.0.106:11212两个服务端实例. 2.示例代码: String[] servers = { "192.168.0.106:11211", "192.168.0.106:11212" }; SockIOPool pool =

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

JDK 源码 阅读 - 2 - 设计模式 - 创建型模式

A.创建型模式 抽象工厂(Abstract Factory) javax.xml.parsers.DocumentBuilderFactory DocumentBuilderFactory通过FactoryFinder实例化具体的Factory. 使用例子: DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilder

CI源码阅读

CodeIgniter源码分析 http://calixwu.com/2014/11/codeigniter-yuanmafenxi.html CI框架源码阅读笔记 http://www.cnblogs.com/ohmygirl/p/4052686.html

《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分

这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecut