Mari kita lihat secara langsung fungsi zmalloc tersuai dalam kod sumber Redis (bukan versi terkini Fungsi ini digunakan dengan cara yang sama seperti fungsi biasa seperti malloc. Perbezaannya terletak pada butiran pelaksanaan dalamannya.
batal *zmalloc(saiz_t) {
// Peruntukkan memori; void *ptr = malloc(saiz + PREFIX_SIZE);
// Kegagalan peruntukan membuang pengecualian; Jika (!ptr) zmalloc_oom_handler(saiz);
// Bolehkah sistem menggunakan fungsi "malloc_size"?
#ifdef MEMPUNYAI_MALLOC_SIZE
Update_zmalloc_stat_alloc(zmalloc_size(ptr));
Kembali ptr;
#lain
//Simpan saiz sebenar data yang diperuntukkan dalam medan data; *((saiz_t*)ptr) = saiz;
// Kira penggunaan memori selepas penjajaran dan kemas kini pembolehubah "used_memory"
Kemas kini_zmalloc_stat_alloc(saiz + PREFIX_SIZE);
// Kembalikan kedudukan awal badan data; Kembalikan (char*)ptr + PREFIX_SIZE;
#endif
}
Malah, fungsi malloc dalam perpustakaan standard sudah boleh menyelaraskan memori yang diperuntukkan secara automatik, jadi tujuan utama kaedah zmalloc di sini adalah untuk mengira dengan tepat saiz memori yang diperuntukkan untuk setiap storan data. Setiap kali memori diperuntukkan, zmalloc akan menambah ruang memori tambahan bersaiz PREFIX_SIZE kepada saiz memori data yang diperuntukkan Makro PREFIX_SIZE ini mewakili saiz ruang alamat memori maksimum (size_t) sistem semasa. Di sini kita boleh merujuk ruang saiz PREFIX_SIZE ini sebagai bahagian "pengepala data" unit storan.
Struktur unit storan versi pertama Redis
Seperti yang ditunjukkan dalam rajah di atas, melalui pernyataan *((size_t*)ptr) = size, Redis menyimpan saiz blok data yang diperuntukkan sebenar dalam bait PREFIX_SIZE pertama bagi blok memori yang diperuntukkan pada masa ini, iaitu, dalam pengepala data, dan dalam entiti data binari berikut sebenarnya disimpan dalam ruang memori saiz "saiz". Fungsi bernama update_zmalloc_stat_alloc di sini mengekalkan pembolehubah global bernama used_memory secara dalaman, yang mengumpul saiz memori yang baru diperuntukkan setiap kali. Fungsi ini mengembalikan penuding offset pada penghujungnya, menunjuk ke bahagian badan data memori yang diperuntukkan pada masa ini. Butiran pelaksanaan khusus bagi fungsi update_zmalloc_stat_alloc adalah seperti berikut.
#define update_zmalloc_stat_alloc(__n) lakukan {
saiz_t _n = (__n);
// Penyiapan memori manual; Jika (_n&(saiz(panjang)-1)) _n += saiz(panjang)-(_n&(saiz(panjang)-1)); atomicIncr(memori_terpakai, __n); } manakala(0)
Perkara penting yang perlu diperhatikan di sini ialah baris _n += sizeof(long)-(_n&(sizeof(long)-1));. Keseluruhan fungsi makro terlebih dahulu menentukan sama ada saiz memori yang diperuntukkan kali ini ialah gandaan integer saiz(panjang) (mesin 64-bit sepadan dengan penjajaran memori 8-bait; mesin 32-bit sepadan dengan penjajaran memori 4-bait), jika tidak Kemudian gunakan pernyataan yang kami berikan sebelum ini untuk menambah ruang pemegang tempat yang sepadan selepas segmen data untuk membentuk bilangan bit untuk memenuhi keperluan penjajaran memori (4/8 bait). Fungsi atomicIncr akhir digunakan untuk mengemas kini nilai pembolehubah used_memory global sambil memastikan keselamatan benang.
Proses pelepasan memori dan peruntukan memori dalam versi Redis ini adalah sebaliknya. Kod yang ditunjukkan di bawah ialah butiran pelaksanaan fungsi "zfree" yang sepadan. Mula-mula, fungsi menunjuk ke alamat pertama medan data yang mengandungi saiz sebenar blok data melalui pernyataan (char*)ptr-PREFIX_SIZE (bergerak ke alamat memori yang lebih rendah), dan kemudian mendapatkan data melalui *(( penyataan size_t*)realptr) Saiz memori sebenar yang diperuntukkan oleh blok (tidak termasuk kawasan penjajaran memori). Akhir sekali, kemas kini nilai pembolehubah global used_memory melalui fungsi update_zmalloc_stat_free dan lepaskan segmen memori.
void zfree(void *ptr) {
#ifndef MEMPUNYAI_SAIZ_MALLOC
batal *realptr;
size_t oldsize;
#endif
Jika (ptr == NULL) kembali;
#ifdef MEMPUNYAI_MALLOC_SIZE
Update_zmalloc_stat_free(zmalloc_size(ptr));
percuma(ptr);
#lain
realptr = (char*)ptr-PREFIX_SIZE;
Saiz lama = *((saiz_t*)realptr);
Update_zmalloc_stat_free(oldsize+PREFIX_SIZE);
percuma(realptr);
#endif
}
Seperti yang ditunjukkan di bawah, jika kita melihat butiran pelaksanaan fungsi update_zmalloc_stat_free, anda akan mendapati bahawa proses pelaksanaannya adalah serupa dengan fungsi update_zmalloc_stat_alloc sebelumnya. Dengan mengira saiz bait memori yang perlu ditambah dan menolak saiz ruang memori yang sepadan daripada pembolehubah used_memory, penggunaan ruang memori boleh dikira dengan tepat.
#define update_zmalloc_stat_free(__n) lakukan {
saiz_t _n = (__n);
Jika (_n&(saiz(panjang)-1)) _n += saiz(panjang)-(_n&(saiz(panjang)-1)); atomicDecr(memori_terpakai,__n);
} manakala(0)
Atas ialah kandungan terperinci Contoh analisis fungsi zmalloc Redis. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!