具体的には:
Google の TC_MALLOC ライブラリがシステムに存在する場合は、元の malloc 関数ファミリーの代わりに tc_malloc 関数ファミリーを使用します。
現在のシステムが Mac システムの場合は、メモリ割り当て機能を使用します。
他の場合には、割り当てられたスペースのサイズを記録するために、割り当てられた各スペースの先頭に追加の固定長フィールドが割り当てられます。
ソース コードはそれぞれ config.h と zmalloc.c にあります。
/* config.h */
#if Definition(USE_TCMALLOC)
#include
#if TC_VERSION_MAJOR >= 1 && TC_VERSION_MINOR >= 6
#define HAVE_MALLOC_SIZE 1
#define redis_malloc_size(p) tc_malloc_size(p)
#endif
#elif 定義(__APPLE__)
#include
#define HAVE_MALLOC_SIZE 1
#define redis_malloc_size(p) malloc_size( p )
#endif
/* zmalloc.c */
#ifdef HAVE_MALLOC_SIZE
#define PREFIX_SIZE (0)
# else
#if 定義されている場合(__sun)
#define PREFIX_SIZE (sizeof(long long))
#else
#define PREFIX_SIZE (sizeof( size_t ))
#endif
#endif
Mac プラットフォームの tc_malloc と malloc 関数ファミリーは、割り当てられた領域のサイズを計算する関数を提供するため (それぞれ tc_malloc_size と malloc_size) ) なので、サイズを記録するために別のスペースを割り当てる必要はありません。 Linux および Sun プラットフォームの場合、割り当てられた領域のサイズを記録する必要があります。 Linux の場合は、sizeof(size_t) 固定長フィールド レコードを使用し、Sun OS の場合は、sizeof(long long) 固定長フィールド レコードを使用します。それが、上記のソース コードの PREFIX_SIZE マクロです。
この文をもう一度表現してください: このレコードの目的は、現在のプロセスによって占有されているメモリの量を計算することです。 zmalloc.c には、次のような静的変数があります。
static size_t used_memory = 0;
これは、プロセスが現在占有しているメモリの総量を記録します。メモリが割り当てられるか解放されるたびに、この変数を更新する必要があります。メモリを割り当てるときに、割り当てるメモリの量を明確に知ることができるためです。ただし、メモリを解放する場合 (malloc_size 関数を提供しないプラットフォームの場合)、解放するメモリへのポインタを指定するだけでは、どれだけのスペースが解放されるのかを知ることはできません。この場合、PREFIX_SIZEで指定された固定長フィールドが機能し、そこに記録されている情報から空間のサイズを取得することができる。 zmalloc 関数は次のとおりです (無関係なコードを削除します):
void *zmalloc(size_t size) {
void *ptr = malloc(size PREFIX_SIZE);
if ( !ptr) zmalloc_oom(size);
*((size_t*)ptr) = size;
update_zmalloc_stat_alloc(size PREFIX_SIZE,size);
return (char*) ptr PREFIX_SIZE;
。 Mac システムで実行している場合、または tc_malloc を使用している場合、PREFIX_SIZE の値はゼロです。次に、ポインタ ptr が指すメモリ ブロックの最初の size_t バイトを使用して、メモリ ブロックに割り当てられたサイズを記録します。最後に返されるのは、レコード領域を超えたポインターです。 zfree 関数も同様です (無関係なコードを削除しています):
void zfree(void *ptr) {
void *realptr;
size_t oldsize;
if ( ptr == NULL) return;
realptr = (char*)ptr-PREFIX_SIZE;
oldsize = *((size_t*)realptr);
update_zmalloc_stat_free( oldsize PREFIX_SIZE );
free(realptr);
#endif
}
まずポインタを PREFIX_SIZE だけ前方に移動し、次に保存されたスペースを取り出します。スペースの長さを割り当てるとき。最後に、スペース全体を解放します。
2 つのマクロ update_zmalloc_stat_alloc(__n,__size) と update_zmalloc_stat_free(__n) は、メモリの割り当てまたは解放時に used_memory 変数を更新する役割を果たします。これをマクロとして定義するのは、主に効率を考慮したためです。次のように、これを関数に復元します。
void update_zmalloc_stat_alloc(__n,__size)
{
do {
size_t _n = (__n );
size_t _stat_slot = (__size < ZMALLOC_MAX_ALLOC_STAT) ? __size : ZMALLOC_MAX_ALLOC_STAT; if (_n&(sizeof(long)-1)) _n = sizeof(long)-(_n&(sizeof(long)-1)); if (zmalloc_thread_safe) { pthread_mutex_lock(&used_memory_mutex); 使用済みメモリ = _n; zmalloc_allocations[_stat_slot]; pthread_mutex_unlock(&used_memory_mutex); } それ以外 { 使用済みメモリ = _n; zmalloc_allocations[_stat_slot]; } しながら(0) } void update_zmalloc_stat_free(__n) { する { サイズ_t _n = (__n); if (_n&(sizeof(long)-1)) _n = sizeof(long)-(_n&(sizeof(long)-1)); if (zmalloc_thread_safe) { pthread_mutex_lock(&used_memory_mutex); 使用済みメモリ -= _n; pthread_mutex_unlock(&used_memory_mutex); } それ以外 { 使用済みメモリ -= _n; } しながら(0) } コード内の used_memory 変数を更新することに加えて、他にも注意すべき点がいくつかあります。 まず、_n の下位ビットが切り上げられ、最終的に _n は sizeof(long) の倍数になります。たとえば、32 ビット システムの場合、sizeof(long) == 100 (バイナリ)になります。アップすると、下位 2 ビットは 0 になります。 プロセス内に複数のスレッドがある場合、変数を更新するときにロックをロックする必要があります。 zmalloc 関数で更新される別の統計: zmalloc_allocations[] があります。 zmalloc.c では、zmalloc_allocations は次のように定義されます。 size_t zmalloc_allocations[ZMALLOC_MAX_ALLOC_STAT 1]; その機能は、プログラムがメモリを割り当てるときに、さまざまなサイズのスペースに対するリクエストの数をカウントすることです。統計領域の範囲は 1 バイトから 256 バイトであり、256 バイトを超える領域は 256 としてカウントされます。統計結果は、zmalloc_allocations_for_size 関数を呼び出すことによって返されます。 size_t zmalloc_allocations_for_size(size_t サイズ) { if (size > ZMALLOC_MAX_ALLOC_STAT) return 0;
Return zmalloc_allocations[size];
}
zmalloc_used_memory 関数を呼び出すと、別のメモリ使用量統計が返されます。
Size_t zmalloc_used_memory(void) {
size_t um;
if (zmalloc_thread_safe) pthread_mutex_lock(&used_memory_mutex);
um = used_memory;
if (zmalloc_thread_safe) pthread_mutex_unlock(&used_memory_mutex);
return um;
}
さらに、zmalloc.c は、さまざまなシステム用の zmalloc_get_rss 関数も実装します。 、メモリ使用量のシステム統計は、/proc/$pid/stat ファイルを読み取ることで取得されます。
以上がRedis のメモリ割り当てと使用量統計の手法は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。