MySQL原始碼解讀之資料結構-動態陣列
MySQL原始碼解讀之資料結構-動態陣列
有時候在使用陣列時,不能確定陣列的大小。遇到這種情況在宣告陣列時,如果長度過小在使用時會導致陣列溢位,長度過長會造成記憶體空間的浪費。因此動態陣列的出現就是為了解決這個問題,在宣告陣列時不指定大小,在執行時具有可以改變陣列大小的能力。
在MySQL中,自身定義了許多資料結構。存放在原始碼的mysys目錄,原始碼中通過這些資料結構來組織資料,更容易實現跨平臺。
原始碼解讀
先來看一眼MySQL原始碼中動態陣列的定義:
[原始碼路徑:include/my_sys.h, mysys/array.cc]
struct DYNAMIC_ARRAY { uchar*buffer{nullptr}; uint elements{0}, max_element{0}; uint alloc_increment{0}; uint size_of_element{0}; PSI_memory_key m_psi_key{PSI_NOT_INSTRUMENTED}; };
可以看到,DYNAMIC_ARRAY是一個結構體。每個元素的解釋如下:
- uchar *buffer{nullptr} 定義一個uchar型別的指標,指向動態陣列。
- uint elements{0} 陣列中元素的個數,預設值為0
- uint max_element{0} 陣列的總長度
- uint alloc_increment {0} 當陣列元素寫滿陣列時,自動擴充套件的長度
- uint size_of_element{0} 陣列中單個元素的大小(size_of)
- PSI_memory_key m_psi_key{PSI_NOT_INSTRUMENTED} 記憶體資源檢測,巨集定義PSI_NOT_INSTRUMENTED預設值為0,不開啟檢測
插話:PSI是用來評估系統資源壓力的,CPU、記憶體、IO。參考部落格:純乾貨,PSI 原理解析與應用
接下來來看一下MySQL中對動態陣列的操作函式:
1、my_init_dynamic_array 陣列初始化
bool my_init_dynamic_array(DYNAMIC_ARRAY *array, PSI_memory_key psi_key,uint element_size, void *init_buffer, uint init_alloc, uint alloc_increment)
函式介紹:
array 指向動態陣列的指標
element_size 單個元素的大小(size_of)
init_buffer 初始緩衝區指標
init_alloc 初始元素個數,如果傳入為0,則init_alloc = alloc_increment。
alloc_increment 新增新元素時,陣列擴充套件的增量大小。如果傳入為0,會根據元素大小進行計算,計算方法自行檢視程式碼
如果初始化記憶體分配失敗,那麼這個資料也是可用的。所以這個函式的返回值永遠是 false,也就是OK的狀態。
2、insert_dynamic 插入一個元素
bool insert_dynamic(DYNAMIC_ARRAY *array, const void *element)
函式介紹:
array 指向動態陣列的指標
element 將被插入的元素
如果elements==max_element,則記憶體空間已經使用完,需要呼叫alloc_dynamic函式realloc空間。記憶體重新分配成功或者記憶體空間沒用完,直接在當前陣列的最後插入元素。
3、alloc_dynamic 為下一個元素分配記憶體空間
void *alloc_dynamic(DYNAMIC_ARRAY *array)
函式介紹:
分配新的元素空間,記憶體空間已經使用完,需要realloc空間,並把原來空間的記憶體memcpy過來。
4、delete_dynamic 刪除動態陣列
void delete_dynamic(DYNAMIC_ARRAY *array)
函式介紹:
刪除動態陣列,釋放記憶體。