1. 程式人生 > 其它 >MySQL原始碼解讀之資料結構-動態陣列

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)

函式介紹:

刪除動態陣列,釋放記憶體。