搜尋
首頁資料庫mysql教程MySQL MEM_ROOT詳細講解
MySQL MEM_ROOT詳細講解Nov 05, 2016 pm 05:07 PM
mysqlroot

這篇文章會詳細解說MySQL中使用非常廣泛的MEM_ROOT的結構體,同時省去debug部分的信息,僅分析正常情況下,mysql中使用MEM_ROOT來做內存分配的部分。

在具體分析之前我們先例舉在該結構體使用過程中用到的一些宏:

#define MALLOC_OVERHEAD 8 //分配过程中,需要保留一部分额外的空间
#define ALLOC_MAX_BLOCK_TO_DROP 4096 //后续会继续分析该宏的用途
#define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP 10 //后续会继续分析该宏的用途

#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double))
#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1))

#define ALLOC_ROOT_MIN_BLOCK_SIZE (MALLOC_OVERHEAD + sizeof(USED_MEM) + 8)
/* Define some useful general macros (should be done after all headers). */
/*作者:www.manongjc.com  */
#define MY_MAX(a, b) ((a) > (b) ? (a) : (b)) //求两个数值之间的最大值
#define MY_MIN(a, b) ((a) < (b) ? (a) : (b)) //求两个数值之间的最小值

下面再來看看MEM_ROOT結構體相關的資訊:

typedef struct st_mem_root
{
    USED_MEM    *free;                  /* free block link list的链表头指针 */
    USED_MEM    *used;                  /* used block link list的链表头指针 */
    USED_MEM    *pre_alloc;             /* 预先分配的block */
    size_t        min_malloc;             /* 如果block剩下的可用空间小于该值,将会从free list移动到used list */
    size_t        block_size;             /* 每次初始化的空间大小 */
    unsigned int    block_num;              /* 记录实际的block数量,初始化为4 */
    unsigned int    first_block_usage;      /* free list中的第一个block 测试不满足分配空间大小的次数 */
    void (*error_handler)( void );          /* 分配失败的错误处理函数 */
} MEM_ROOT;

以下是分配具體的block資訊.

typedef struct st_used_mem
{ 
    struct st_used_mem *next; //指向下一个分配的block
    unsigned int left; //该block剩余的空间大小
    unsigned int size; //该block的总大小
} USED_MEM;

void init_alloc_root( MEM_ROOT *mem_root, size_t block_size, size_t pre_alloc_size __attribute__( (unused) ) )
{
    mem_root->free            = mem_root->used = mem_root->pre_alloc = 0;
    mem_root->min_malloc        = 32;
    mem_root->block_size        = block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
    mem_root->error_handler        = 0;
    mem_root->block_num        = 4; /* We shift this with >>2 */
    mem_root->first_block_usage    = 0;
}

以下是分配具體的block資訊.

void *alloc_root( MEM_ROOT *mem_root, size_t length )
{
    size_t        get_size, block_size;
    uchar        * point;
    reg1 USED_MEM    *next = 0;
    reg2 USED_MEM    **prev;

    length = ALIGN_SIZE( length );
    if ( (*(prev = &mem_root->free) ) != NULL )
    {
        if ( (*prev)->left < length &&
             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    = 0;
        }
        for ( next = *prev; next && next->left < length; next = next->next )
            prev = &next->next;
    }
    if ( !next )
    {       /* Time to alloc new block */
        block_size    = mem_root->block_size * (mem_root->block_num >> 2);
        get_size    = length + ALIGN_SIZE( sizeof(USED_MEM) );
        get_size    = MY_MAX( get_size, block_size );

        if ( !(next = (USED_MEM *) my_malloc( get_size, MYF( MY_WME | ME_FATALERROR ) ) ) )
        {
            if ( mem_root->error_handler )
                (*mem_root->error_handler)();
            DBUG_RETURN( (void *) 0 );                              /* purecov: inspected */
        }
        mem_root->block_num++;
        next->next    = *prev;
        next->size    = get_size;
        next->left    = get_size - ALIGN_SIZE( sizeof(USED_MEM) );    /* bug:如果该block是通过mem_root->block_size * (mem_root->block_num >> 2)计算出来的,则已经去掉了ALIGN_SIZE(sizeof(USED_MEM),这里重复了。 */
        *prev        = next;
    }

    point = (uchar *) ( (char *) next + (next->size - next->left) );
/*TODO: next part may be unneded due to mem_root->first_block_usage counter*/
/* 作者:www.manongjc.com */
    if ( (next->left -= length) < 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    = 0;
    }
}
MySQL MEM_ROOT詳細講解
for (next= *prev ; next && next->left < length ; next= next->next)
prev= &next->next;
}

以下是分配具體的block資訊.

rrreee

rrreee其實MEM_ROOT在分配過程中,是透過雙向鍊錶來管理used和free的block:

MySQL MEM_ROOT詳細講解

MEM_ROOT的初始化過程如下:

rrreee

初始化過程中,block_size空間為編號_OTlock_size-ALLblock_OT_size。因為在記憶體不夠,需要擴充時,是透過mem_root->block_num >>2 * block_size 來擴充的,所以mem_root->block_num >>2 至少為1,因此在初始化的過程中mem_root->block_num=4(註:4>>2=1)。



下面來看看具體分配記憶體的步驟:
rrreee
上述程式碼的具體邏輯如下:

1.查看free鍊錶,尋找滿足空間的block。如果找到了合適的block,則:
1.1 直接傳回該block從size-left處的初始位址即可。當然,在free list遍歷的過程中,會去判斷free list
中第一個block中left的空間不滿足需要分配的空間,且該block中已經查找過了10次
(ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP)滿足都不分配長度,且該block剩餘空間小於

4k(ALLOC_MAX_BLOCK_TO_DROP),則將該block 移至used鍊錶中。

2.如果free鍊錶中,沒有合適的block,則:

2.1 分配mem_root->block_size * (mem_root->block_num >> 2)和length+ALIGN_SIZE(sizeof(USED_MEM))

中比較大的作為新的block記憶體空間。

2.2 依照該block的使用情況,將該block掛在used或free鍊錶上。 MySQL MEM_ROOT詳細講解

這裡需要注意的是二級指標的使用:

rrreee

prev指向的是最後一個block的next指向的地址的地址:

MySQL MEM_ROOT詳細講解

所以將prev的地址替換為new block的地址,即將該地址new block加到了free list的結尾:*prev=next;


總結:🎜🎜MEM_ROOT的記憶體分配採用的是啟發式分配演算法,隨著後續block的數量越多,單一block的記憶體也會越大:block_size= mem_root->block_size * (mem_root->block_num >> 2) .🎜🎜🎜🎜
陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
以超级用户身份登录Ubuntu以超级用户身份登录UbuntuMar 20, 2024 am 10:55 AM

在Ubuntu系统中,root用户通常是禁用状态的。要激活root用户,可以使用passwd命令设置密码,然后使用su-命令以root身份登录。根用户是具有系统管理权限且不受限制的用户。他拥有访问和修改文件、用户管理、软件安装和删除,以及系统配置更改等权限。根用户与普通用户有着明显的区别,根用户拥有系统中最高的权限和更广泛的控制权。根用户可以执行重要的系统命令和编辑系统文件,而普通用户则无法做到这一点。在本指南中,我将探讨Ubuntu根用户,如何以根用户身份登录,以及它与普通用户的不同之处。注意

Linux怎么修改root用户名称Linux怎么修改root用户名称May 18, 2023 pm 07:50 PM

1、以CentOS为例,登录后修改/etc/passwd与/etc/shadow,将第一行开始的root改为新的用户名(比如admin),修改之后通过wq!保存。2、修改并保存后,重启服务器后即可生效,可以看下文件的权限,可以看到所属帐号一栏变为admin了,如下:注:在Linux中默认的最高管理权限用户是root,uid为0。在系统中只识别uid,因此只要uid为0,系统就视为最高管理用户。但是对于应用程序可能会存在一定的问题,有些软件默认使用的是root用户,所以在对软件应用的了解有限的情况

手把手使用 Python 删除 Windows 下的长路径文件手把手使用 Python 删除 Windows 下的长路径文件Apr 12, 2023 pm 01:31 PM

0x01 文章背景近期,笔者所在公司的某业务系统的存储临近极限,服务器马上就要跑不动了,由于该业务系统A包含多个子系统A1、A2、A3 ... An,这些子系统的中间存储文件由于设计原因,都存储在同一个父级目录之内,唯一不同的是,不同子系统产生的文件和文件夹的名字都以该子系统名开始。如A1子系统产生的文件命名方式均为A1xxxxxx​, A2子系统产生的文件名均为A2xxxxx。现在要删除其中一些子系统的历史文件,以释放服务器空间,几十T的数据,存放在一起,手动删除肯定不显示,只能借助程序自动化

Nginx配置中指令root和alias的区别是什么Nginx配置中指令root和alias的区别是什么May 12, 2023 pm 12:16 PM

root和alias都可以定义在location模块中,都是用来指定请求资源的真实路径,比如:location/i/{root/data/w3;}请求http://foofish.net/i/top.gif这个地址时,那么在服务器里面对应的真正的资源是/data/w3/i/top.gif文件注意:真实的路径是root指定的值加上location指定的值。而alias正如其名,alias指定的路径是location的别名,不管location的值怎么写,资源的真实路径都是alias指定的路径,比如

mysql怎么替换换行符mysql怎么替换换行符Apr 18, 2022 pm 03:14 PM

在mysql中,可以利用char()和REPLACE()函数来替换换行符;REPLACE()函数可以用新字符串替换列中的换行符,而换行符可使用“char(13)”来表示,语法为“replace(字段名,char(13),'新字符串') ”。

手机root的好处和坏处手机root的好处和坏处Jul 06, 2023 pm 04:53 PM

手机root的好处:1、可以备份系统;2、可以使用高级的程序;3、可以修改和删除系统的程序;4、可以把程序安装在sd卡上;5、可以修改系统字体等等。坏处:1、手机root后容易被木马病毒侵入;2、可能因为不彻底以及软件兼容性等问题,导致系统损坏出现系统运行问题;3、手机root后软件错删系统文件导致系统错误;4、手机root后用户隐私有被泄露风险等等。

mysql怎么将varchar转换为int类型mysql怎么将varchar转换为int类型May 12, 2022 pm 04:51 PM

转换方法:1、利用cast函数,语法“select * from 表名 order by cast(字段名 as SIGNED)”;2、利用“select * from 表名 order by CONVERT(字段名,SIGNED)”语句。

MySQL复制技术之异步复制和半同步复制MySQL复制技术之异步复制和半同步复制Apr 25, 2022 pm 07:21 PM

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于MySQL复制技术的相关问题,包括了异步复制、半同步复制等等内容,下面一起来看一下,希望对大家有帮助。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境