mysql层的内存分配
参考 http://www.cnblogs.com/justfortaste/p/3198406.html
http://m.blog.csdn.net/blog/IT_PCode/17007833
http://blog.chinaunix.net/uid-28364803-id-3419777.html
http://blog.chinaunix.net/uid-26896862-id-3412033.html
mysql数据库分mysql层和存储引擎层,每个层都有各自的分配内存方法
mysql层分配内存方法比较简单
当一个请求过来后,使用一个线程为其服务,mysql层为它分配内存
mysql层mem_root
- typedef struct st_used_mem
- { /* struct for once_alloc (block) */
- struct st_used_mem *next; /* Next block in use */
- unsigned int left; /* memory left in block */
- unsigned int size; /* size of block */
- } USED_MEM;
- typedef struct st_mem_root
- {
- USED_MEM *free; /* blocks with free memory in it */
- USED_MEM *used; /* blocks almost without free memory */
- USED_MEM *pre_alloc; /* preallocated block */
- /* if block have less memory it will be put in 'used' list */
- size_t min_malloc;
- size_t block_size; /* initial block size */
- unsigned int block_num; /* allocated blocks counter */
- /*
- first free block in queue test counter (if it exceed
- MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list)
- */
- unsigned int first_block_usage;
- void (*error_handler)(void);
- } MEM_ROOT;
- mysql内存池
- mysql内部使用的内存管理程序,可以实现多次申请内存块, 中途任何时刻失败, 或者下次使用前释放内存, 无需再关心每次申请和释放了哪些内存.
- 工作原理:
- 初始化定义每次分配的最小内存块大小M,如果申请一次内存, 大小为X, X大于M, 就分配一块X的内存, 加入到管理链表中.如果小于的话, 看之前剩余的还够不够, 如果足够的话, 返回之前多余的内存地址.如果不够,则申请这么大的内存, 也计入链表中。
- 释放是一次性的,也可以不释放内存,而是标记已经使用的内存为“未使用”,下次同样的应用可以继续使用。
- 创建内存池
- /*
- Initialize memory root
- SYNOPSIS
- init_alloc_root()
- mem_root - memory root to initialize
- block_size - size of chunks (blocks) used for memory allocation
- (It is external size of chunk i.e. it should include
- memory required for internal structures, thus it
- should be no less than ALLOC_ROOT_MIN_BLOCK_SIZE)
- pre_alloc_size - if non-0, then size of block that should be
- pre-allocated during memory root initialization.
- DESCRIPTION
- This function prepares memory root for further use, sets initial size of
- chunk for memory allocation and pre-allocates first block if specified.
- Altough error can happen during execution of this function if
- pre_alloc_size is non-0 it won't be reported. Instead it will be
- reported as error in first alloc_root() on this memory root.
- */
- void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
- uint pre_alloc_size __attribute__((unused))) {
- DBUG_ENTER("init_alloc_root");
- mem_root->free = mem_root->used = mem_root->pre_alloc = ;
- mem_root->min_malloc = ;
- mem_root->block_size = block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
- mem_root->error_handler = ;
- mem_root->block_num = ; /* We shift this with >>2 */
- mem_root->first_block_usage = ;
- if (pre_alloc_size) {
- if ((mem_root->free = mem_root->pre_alloc = (USED_MEM*) my_malloc(
- pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM)),
- MYF())))
- {
- mem_root->free->size= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM));
- mem_root->free->left= pre_alloc_size;
- mem_root->free->next= ;
- }
- }
- DBUG_VOID_RETURN;
- }
- 申请内存
- gptr alloc_root(MEM_ROOT *mem_root, unsigned int Size) {
- uint get_size, block_size;
- gptr point;
- reg1 USED_MEM *next = ;
- reg2 USED_MEM **prev;
- DBUG_ENTER("alloc_root");DBUG_ASSERT(alloc_root_inited(mem_root));
- Size = ALIGN_SIZE(Size);
- if ((*(prev = &mem_root->free)) != NULL)
- {
- if ((*prev)->left < Size
- && mem_root->first_block_usage++
- >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP
- && (*prev)->left < ALLOC_MAX_BLOCK_TO_DROP)
- {
- next = *prev;
- *prev = next->next; /* Remove block from list */
- next->next = mem_root->used;
- mem_root->used = next;
- mem_root->first_block_usage = ;
- }
- for (next = *prev; next && next->left < Size; next = next->next)
- prev = &next->next;
- }
- if (!next) { /* Time to alloc new block */
- block_size = mem_root->block_size * (mem_root->block_num >> );
- get_size = Size + ALIGN_SIZE(sizeof(USED_MEM));
- get_size = max(get_size, block_size);
- if (!(next = (USED_MEM*) my_malloc(get_size, MYF(MY_WME)))) {
- if (mem_root->error_handler)
- (*mem_root->error_handler)();
- return ((gptr) ); /* purecov: inspected */
- }
- mem_root->block_num++;
- next->next = *prev;
- next->size = get_size;
- next->left = get_size - ALIGN_SIZE(sizeof(USED_MEM));
- *prev = next;
- }
- point = (gptr) ((char*) next + (next->size - next->left));
- /*TODO: next part may be unneded due to mem_root->first_block_usage counter*/
- if ((next->left -= Size) < mem_root->min_malloc) { /* Full block */
- *prev = next->next; /* Remove block from list */
- next->next = mem_root->used;
- mem_root->used = next;
- mem_root->first_block_usage = ;
- }DBUG_RETURN(point);
- }
- 释放内存
- /*
- Deallocate everything used by alloc_root or just move
- used blocks to free list if called with MY_USED_TO_FREE
- SYNOPSIS
- free_root()
- root Memory root
- MyFlags Flags for what should be freed:
- MY_MARK_BLOCKS_FREED Don't free blocks, just mark them free
- MY_KEEP_PREALLOC If this is not set, then free also the
- preallocated block
- NOTES
- One can call this function either with root block initialised with
- init_alloc_root() or with a bzero()-ed block.
- It's also safe to call this multiple times with the same mem_root.
- */
- void free_root(MEM_ROOT *root, myf MyFlags) {
- reg1 USED_MEM *next, *old;
- DBUG_ENTER("free_root");
- if (!root) /* QQ: Should be deleted */
- DBUG_VOID_RETURN; /* purecov: inspected */
- if (MyFlags & MY_MARK_BLOCKS_FREE)
- {
- mark_blocks_free(root);
- DBUG_VOID_RETURN;
- }
- if (!(MyFlags & MY_KEEP_PREALLOC))
- root->pre_alloc = ;
- for (next = root->used; next;) {
- old = next;
- next = next->next;
- if (old != root->pre_alloc)
- my_free((gptr) old, MYF());
- }
- for (next = root->free; next;) {
- old = next;
- next = next->next;
- if (old != root->pre_alloc)
- my_free((gptr) old, MYF());
- }
- root->used = root->free = ;
- if (root->pre_alloc) {
- root->free = root->pre_alloc;
- root->free->left = root->pre_alloc->size - ALIGN_SIZE(sizeof(USED_MEM));
- TRASH_MEM(root->pre_alloc);
- root->free->next = ;
- }
- root->block_num = ;
- root->first_block_usage = ;
- DBUG_VOID_RETURN;
- }
- 内存池使用实例
- void test_myalloc() {
- MEM_ROOT root;
- char *str;
- init_alloc_root(&root, << , << );
- str = (char *) alloc_root(&root, * sizeof(double));
- if (NULL == str)
- printf("cannot get memory for alloc root for str\n");
- strcpy(str, "hello\n");
- puts(str);
- //mark free, can be used again
- free_root(&root, MY_MARK_BLOCKS_FREE);
- //free, can not be used
- free_root(&root, );
- }
- void my_free(void *ptr)
- {
- DBUG_ENTER("my_free");
- DBUG_PRINT("my",("ptr: %p", ptr));
- free(ptr);
- DBUG_VOID_RETURN;
- }
mysql层的内存分配的更多相关文章
- MYSQL,innodb_buffer_pool_size内存分配
为MYSQL.innodb_buffer_pool_size=8G.MySQL一起动就会将占用掉8G内存(觉得TOP能够看到内存被使用了8G),可是近期才细致研究一下.原来不是这种(可能自己对Linu ...
- 深入理解Linux内存分配
深入理解Linux内存分配 为了写一个用户层程序,你也许会声明一个全局变量,这个全局变量可能是一个int类型也可能是一个数组,而声明之后你有可能会先初始化它,也有可能放在之后用到它的时候再初始化.除此 ...
- Android O Bitmap 内存分配
我们知道,一般认为在Android进程的内存模型中,heap分为两部分,一部分是native heap,一部分是Dalvik heap(实际上也是native heap的一部分). Andro ...
- mysql 与linux ~ 内存分析与调优
一 简介:linux内存和mysql二 分类 1 用户空间和内核空间 用户空间内存,从低到高分别是五种不同的内存段 1 只读段 包含代码和常量等 2 数据段 包含全局 ...
- 高性能go服务之高效内存分配
高性能go服务之高效内存分配 手动内存管理真的很坑爹(如C C++),好在我们有强大的自动化系统能够管理内存分配和生命周期,从而解放我们的双手. 但是呢,如果你想通过调整JVM垃圾回收器参数或者是优化 ...
- TCMalloc优化MySQL、Nginx内存管理
TCMalloc的全称为Thread-Caching Malloc,是谷歌开发的开源工具google-perftools中的一个成员. 与标准的glibc库的Malloc相比,TCMalloc库在内存 ...
- java\c程序的内存分配
JAVA 文件编译执行与虚拟机(JVM)介绍 Java 虚拟机(JVM)是可运行Java代码的假想计算机.只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该 ...
- <转载>内存管理内幕-动态分配的选择、折衷和实现 对malloc内存分配有个简单的描述,对内存管理有个大致的说明
这篇文章看后感觉不错,和我在glibc下的hurdmalloc.c文件里关于malloc的实现基本意思相同,同时,这篇文章还介绍了一些内存管理方面的知识,值得推荐. 原文链接地址为:http://ww ...
- c++内存分配
[导语] 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C++中无处不 ...
随机推荐
- arm家族小检阅
- spring-boot @Async 的使用、自定义Executor的配置方法
1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent.Executor Spring 已经实现的异常线程池: 1. SimpleAsyncT ...
- 2018.10.12 NOIP模拟 数据结构(线段树)
传送门 sb线段树题居然还卡常. 修改操作直接更新区间最小值和区间标记下传即可. 询问加起来最多5e65e65e6个数. 因此直接询问5e65e65e6次最小值就行了. 代码
- 2018.09.28 hdu5435A serious math problem(数位dp)
传送门 数位dp卡常题. 写了一发dfs版本的发现过不了233. 于是赶紧转循环版本. 预处理出f数组. f[i][j]f[i][j]f[i][j]表示前i位数异或和为j的方案数. 然后每次直接数位d ...
- 2018.09.14 bzoj2982: combination(Lucas定理)
传送门 貌似就是lucas的板子题啊. 练一练手感觉挺舒服的^_^ 代码: #include<bits/stdc++.h> #define mod 10007 #define ll lon ...
- arduino 与 android 通过TCP进行字节收发
arduino #include <avr/wdt.h> #include <SoftwareSerial.h> #define FPIN 13 SoftwareSerial ...
- dj cookie & session组件
Cookie概述 什么叫Cookie Cookie翻译成中文是小甜点,小饼干的意思.在HTTP中它表示服务器送给客户端浏览器的小甜点.其实Cookie是key-value结构,类似于一个python中 ...
- HDU 3177 Crixalis's Equipment (贪心,差值)
题意:判断 n 件物品是否可以搬进洞里,每件物品有实际体积A和移动时的额外体积 B . 析:第一反应就是贪心,一想是不是按B从大到小,然后一想,不对,比如体积是20,第一个 是A=11, B=19.第 ...
- RepositionBars的用法和参数的意义(引用别人的)
MFC窗口位置管理详细分析及实例 在一般用MFC编写的程序的窗口客户区中,可能有好几个子窗口(具有WM_CHILD风格的窗口).上边是工具栏,中间是视图窗口,下边是状态栏.三个窗 口在框架的客户区里和 ...
- Python学习-34.Python中os模块的一些方法(二)
stat方法: 用于获取文件信息,例如创建时间.文件大小等. import os filestate=os.stat("e:/temp/test.txt") print(files ...