Innodb额外内存池的分配策略以及性能

                                           Innodb额外内存池的分配策略以及性能
                                    作者:明天会更好
                                    QQ:715169549
备注:未经同意,严禁转载,谢谢合作。

//内存池结构体
/** Data structure for a memory pool. The space is allocated using the buddy
algorithm, where free list i contains areas of size 2 to power i. */
struct mem_pool_t{
    byte*        buf;        /*!< memory pool */
    ulint        size;        /*!< memory common pool size */
    ulint        reserved;    /*!< amount of currently allocated
                    memory */
    ib_mutex_t        mutex;        /*!< mutex protecting this struct */
    UT_LIST_BASE_NODE_T(mem_area_t)
            free_list[64];    /*!< lists of free memory areas: an
                    area is put to the list whose number
                    is the 2-logarithm of the area size */
};
//记录内存池中的块的使用情况的结构体
/** Memory area header */
struct mem_area_t{
    ulint        size_and_free;    /*!< memory area size is obtained by
                    anding with ~MEM_AREA_FREE; area in
                    a free list if ANDing with
                    MEM_AREA_FREE results in nonzero */
    UT_LIST_NODE_T(mem_area_t)
            free_list;    /*!< free list node */
};

//额外内存池分配的函数
void srv_general_init(void)
/*==================*/
{
    ut_mem_init();
    /* Reset the system variables in the recovery module. */
    recv_sys_var_init();
    os_sync_init();
    sync_init();
    //    srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
    //  此处执行了额外内存池分配的大小为srv_mem_pool_size
    mem_init(srv_mem_pool_size);
    que_init();
    row_mysql_init();
}

//内存初始化函数
void mem_init(
/*=====*/
    ulint    size)    /*!< in: common pool size in bytes */
{
#ifdef UNIV_MEM_DEBUG

    ulint    i;

    /* Initialize the hash table */
    ut_a(FALSE == mem_hash_initialized);

    mutex_create(mem_hash_mutex_key, &mem_hash_mutex, SYNC_MEM_HASH);

    for (i = 0; i < MEM_HASH_SIZE; i++) {
        UT_LIST_INIT(*mem_hash_get_nth_cell(i));
    }

    UT_LIST_INIT(mem_all_list_base);

    mem_hash_initialized = TRUE;
#endif

    //如果srv_use_sys_malloc的值是由innodb_use_sys_malloc初始化的。
    //    innodb_use_sys_malloc=0表示使用额外内存池一次性分配,以后的释放和申请都是在这个内存池进行的,而不需要额外
    //进行malloc申请
    if (UNIV_LIKELY(srv_use_sys_malloc)) {
        /* When innodb_use_sys_malloc is set, the
        mem_comm_pool won‘t be used for any allocations.  We
        create a dummy mem_comm_pool, because some statistics
        and debugging code relies on it being initialized. */
        size = 1;//如果innodb_use_sys_malloc=1,则在整个mysql运行期间额外内存池的内存池结构体大小(mem_pool_t->size)都是1个字节。
    }
    mem_comm_pool = mem_pool_create(size);
}

srv_use_sys_malloc:
  这个参数是控制innodb 额外内存分配方式;默认是on(1),表示内存申请采用malloc,内存的使用申请情况大小记录在mem_area_t中,额外内存池结构体中的size仅仅是一个字节大小;如果为off(0),则表示使用innodb内存池进行分配。
注意,这里仅仅是针对额外内存池的内存配(UNIV_INTERN mem_pool_t*    mem_comm_pool    = NULL).当srv_use_sys_malloc=0的时候,在mysql启动后,一次性申请srv_mem_pool_size个字节的内存放到mem_pool_t中,并初始化每个使用情况的结构体(mem_area_t)。

如果srv_use_sys_malloc=1,表示内存申请是使用malloc的方式。

mem_heap_create_block_func(
/*=======================*/
    mem_heap_t*    heap,    /*!< in: memory heap or NULL if first block
                should be created */
    ulint        n,    /*!< in: number of bytes needed for user data */
#ifdef UNIV_DEBUG
    const char*    file_name,/*!< in: file name where created */
    ulint        line,    /*!< in: line where created */
#endif /* UNIV_DEBUG */
    ulint        type)    /*!< in: type of heap: MEM_HEAP_DYNAMIC or
                MEM_HEAP_BUFFER */
说明:
   mem_heap_create_block_func中调用mem_area_alloc(&len, mem_comm_pool));这个函数主要是记录mem_pool_t中的free_list信息(申请了多大内存)
此时mem_comm_pool->size都是为1,仅仅变化的是free_list中的信息。

void* mem_area_alloc(
/*===========*/
    ulint*        psize,    /*!< in: requested size in bytes; for optimum
                space usage, the size should be a power of 2
                minus MEM_AREA_EXTRA_SIZE;
                out: allocated size in bytes (greater than
                or equal to the requested size) */
    mem_pool_t*    pool)    /*!< in: memory pool */
   说明:
     mem_area_alloc函数返回return(ut_malloc(size)),使用malloc方式申请额外内存池服务。

//官方说明:
14.13.3 Configuring the Memory Allocator for InnoDB

When InnoDB was developed, the memory allocators supplied with operating systems and run-time libraries were often lacking in performance and scalability. At that time, there were no memory allocator libraries tuned for multi-core CPUs. Therefore, InnoDB implemented its own memory allocator in the mem subsystem. This allocator is guarded by a single mutex, which may become a bottleneck. InnoDB also implements a wrapper interface around the system allocator (malloc and free) that is likewise guarded by a single mutex.

Today, as multi-core systems have become more widely available, and as operating systems have matured, significant improvements have been made in the memory allocators provided with operating systems. New memory allocators perform better and are more scalable than they were in the past. The leading high-performance memory allocators include Hoard, libumem, mtmalloc, ptmalloc, tbbmalloc, and TCMalloc. Most workloads, especially those where memory is frequently allocated and released (such as multi-table joins), benefit from using a more highly tuned memory allocator as opposed to the internal, InnoDB-specific memory allocator.

You can control whether InnoDB uses its own memory allocator or an allocator of the operating system, by setting the value of the system configuration parameter innodb_use_sys_malloc in the MySQL option file (my.cnf or my.ini). If set to ON or 1 (the default), InnoDB uses the malloc and free functions of the underlying system rather than manage memory pools itself. This parameter is not dynamic, and takes effect only when the system is started. To continue to use the InnoDB memory allocator, set innodb_use_sys_malloc to 0.

When the InnoDB memory allocator is disabled, InnoDB ignores the value of the parameter innodb_additional_mem_pool_size. The InnoDB memory allocator uses an additional memory pool for satisfying allocation requests without having to fall back to the system memory allocator. When the InnoDB memory allocator is disabled, all such allocation requests are fulfilled by the system memory allocator.

On Unix-like systems that use dynamic linking, replacing the memory allocator may be as easy as making the environment variable LD_PRELOAD or LD_LIBRARY_PATH point to the dynamic library that implements the allocator. On other systems, some relinking may be necessary. Please refer to the documentation of the memory allocator library of your choice.

Since InnoDB cannot track all memory use when the system memory allocator is used (innodb_use_sys_malloc is ON), the section “BUFFER POOL AND MEMORY” in the output of the SHOW ENGINE INNODB STATUS command only includes the buffer pool statistics in the “Total memory allocated”. Any memory allocated using the mem subsystem or using ut_malloc is excluded.

Note
innodb_use_sys_malloc and innodb_additional_mem_pool_size are deprecated in MySQL 5.6.3 and will be removed in a future release.
时间: 2024-08-24 02:36:06

Innodb额外内存池的分配策略以及性能的相关文章

Memcache 内存分配策略和性能(使用)状态检查

前言: 一直在使用Memcache,但是对其内部的问题,如它内存是怎么样被使用的,使用一段时间后想看看一些状态怎么样?一直都不清楚,查了又忘记,现在整理出该篇文章,方便自己查阅.本文不涉及安装.操作.有兴趣的同学可以查看之前写的文章和Google. 1:参数 memcached -h memcached 1.4.14 -p <num> TCP端口,默认为11211,可以不设置 -U <num> UDP端口,默认为11211,0为关闭 -s <file> UNIX soc

InnoDB 存储引擎的线程与内存池

InnoDB 存储引擎的线程与内存池 InnoDB体系结构如下: 后台线程: 1.后台线程的主要作用是负责刷新内存池中的数据,保证缓冲池中的内存缓存的是最近的数据: 2.另外,将以修改的数据文件刷新到磁盘文件: 3.同时,保证在数据库发生异常的情况下,InnoDB能恢复到正常运行状态. 内存池:InnoDB有多个内存块,这些内存块组成了一个大的内存池.这些内存块包括有:缓冲池(innodb_buffer_pool)和日志缓冲(log_buffer)以及额外内存池(innodb_addtional

程序运行时三种内存分配策略

按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的. 静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求. 栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未

java中内存分配策略及堆和栈的比较

2.1 内存分配策略 按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的. 静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求. 栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区

内存池技术介绍(图文并茂,非常清楚)

看到一篇关于内存池技术的介绍文章,受益匪浅,转贴至此. 原贴地址:http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html 6.1 自定义内存池性能优化的原理 如前所述,读者已经了解到"堆"和"栈"的区别.而在编程实践中,不可避免地要大量用到堆上的内存.例如在程序中维护一个链表的数据结构时,每次新增或者删除一个链表的节点,都需要从内存堆上分配或者释放一定的内存:在维护一个动态数组时,如果动态数组的

内存池技术的原理与实现

6.1 自定义内存池性能优化的原理 如前所述,读者已经了解到"堆"和"栈"的区别.而在编程实践中,不可避免地要大量用到堆上的内存.例如在程序中维护一个链表的数据结构时,每次新增或者删除一个链表的节点,都需要从内存堆上分配或者释放一定的内存:在维护一个动态数组时,如果动态数组的大小不能满足程序需要时,也要在内存堆上分配新的内存空间. 6.1.1 默认内存管理函数的不足 利用默认的内存管理函数new/delete或malloc/free在堆上分配和释放内存会有一些额外的

c++内存池实现

利用C/C++开发大型应用程序中,内存的管理与分配是一个需要认真考虑的部分.本文描述了内存池设计原理并给出内存池的实现代码,代码支持Windows和Linux,多线程安全.内存池设计过程中需要考虑好内存的分配与释放问题,其实也就是空间和时间的矛盾.有的内存池设计得很巧妙,内存分配与需求相当,但是会浪费过多的时间去查找分配与释放,这就得不偿失:实际使用中,我们更多的是关心内存分配的速度,而不是内存的使用效率.基于此,本文按照如下思想设计实现内存池.主要包含三个结构:StiaticMemory, M

Linux简易APR内存池学习笔记(带源码和实例)

先给个内存池的实现代码,里面带有个应用小例子和画的流程图,方便了解运行原理,代码 GCC 编译可用.可以自己上网下APR源码,参考代码下载链接: http://pan.baidu.com/s/1hq6A20G 贴两个之前学习的时候参考的文章地址,大家可以参考: http://www.cnblogs.com/bangerlee/archive/2011/09/01/2161437.html http://blog.csdn.net/flyingfalcon/article/details/2627

Nginx 内存池管理

概述 Nginx 使用内存池对内存进行管理,内存管理的实现类似于前面文章介绍的<STL源码剖析--空间配置器>,把内存分配归结为大内存分配 和 小内存分配.若申请的内存大小比同页的内存池最大值 max 还大,则是大内存分配,否则为小内存分配. 大块内存的分配请求不会直接在内存池上分配内存来满足请求,而是直接向系统申请一块内存(就像直接使用 malloc 分配内存一样),然后将这块内存挂到内存池头部的 large 字段下. 小块内存分配,则是从已有的内存池数据区中分配出一部分内存. Nginx