MySQL內存管理機制淺析
一、placement new的定義
通常情況下,C++中通過用new方式申請內存空間時,是在系統的堆內存空間中進行分配,底層使用C標準庫的malloc()完成內存分配工作。
因此本次申請的內存空間大小,是根據程序運行時對象的大小及使用情況來決定的。
但是某些場景中,可能需要預先分配完成內存空間,然后再把對象"放置"在之前預先分配的內存空間上。即所謂的placement new操作。
定點放置的new操作的語法不同于普通的new操作,比如:我們一般在堆中申請內存空間,通常寫:
Object* o = new Object();
而定點放置new的語法形式為:
Object* o = new (pointer) Object();
這里的pointer就是預先分配好內存塊的首地址。
二、placement new使用場景
傳統堆分配內存方式的弊端:通過new操作符進行堆內存的分配,操作系統需要在堆中找到連續且大小符合要求的內存空間,這個查詢匹配的效率是低下的。
極端情況下可能由于空間不足,導致出現內存分配失敗的問題發生。
placement new分配方式:創建的對象都在預先分配好的內存緩沖區中操作,無需查詢及匹配內存空間,內存分配的時間是常量O(1)。
由于在之前預留的內存空間進行分配,因此不會出現程序運行時由于內存空間不足,導致內存分配失敗的問題。
三、placement new和 MySQL 內存管理機制的關系
正是由于上述placement new的機制特性,因此其非常適合那些對時間,性能要求高,長時間運行,不希望被中斷的應用程序。例如數據庫這類的應用場景,就是很好的例子。
MySQL內部使用mem_root進行內存管理,可以實現多次批量的內存空間申請,并且可以把對象放置到mem_root定義的內存空間中,這樣程序運行失敗或者中途異常crash退出,我們就無需關心是否成功釋放內存。
一切都通過mem_root進行代理操作,整個內存的申請、分配、回收過程透明完成。
四、MySQL中 mem_root 使用場景
//聲明 mem_root 對象
MEM_ROOT execute_mem_root;
Query_arena execute_arena(&execute_mem_root,Query_arena::STMT_INITIALIZED_FOR_SP);
//預分配內存塊空間
init_sql_alloc(key_memory_sp_head_execute_root, &mem_root,
MEM_ROOT_BLOCK_SIZE, 0);
//把thd中的mem_root指針指向execute_mem_root對應的內存塊
thd->swap_query_arena(execute_arena, &backup_arena);
//把對象分配在預先申請的mem_root上
LEX *sublex = new (thd->mem_root) st_lex_local;
//一些邏輯計算操作
......
//釋放表空間
free_root(&execute_mem_root, MYF(0));
總結:MySQL通過mem_root進行內存的統一申請、回收、管理。不但提升了內存分配的效率,提高了系統資源的利用率,而且減少了內存碎片化,是MySQL性能提升的一個重要抓手。
Enjoy GreatSQL :)?