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);
used_memory += _n;
zmalloc_allocations[_stat_slot]++;
pthread_mutex_unlock(&used_memory_mutex);
} else {
used_memory += _n;
zmalloc_allocations[_stat_slot]++;
}
} while(0)
}
void update_zmalloc_stat_free(__n)
{
do {
size_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);
used_memory -= _n;
pthread_mutex_unlock(&used_memory_mutex);
} else {
used_memory -= _n;
}
} while(0)
}
{
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);
used_memory += _n;
zmalloc_allocations[_stat_slot]++;
pthread_mutex_unlock(&used_memory_mutex);
} else {
used_memory += _n;
zmalloc_allocations[_stat_slot]++;
}
} while(0)
}
void update_zmalloc_stat_free(__n)
{
do {
size_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);
used_memory -= _n;
pthread_mutex_unlock(&used_memory_mutex);
} else {
used_memory -= _n;
}
} while(0)
}
代码中除了更新used_memory变量外,还有几个要关注的地方:
①先对_n的低位向上取整,最后_n变为sizeof(long)的倍数,比如对于32位系统,sizeof(long) == 100(二进制),_n向上取整之后,低两位都变为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 size) {
if (size > ZMALLOC_MAX_ALLOC_STAT) return 0;
return zmalloc_allocations[size];
}
if (size > ZMALLOC_MAX_ALLOC_STAT) return 0;
return zmalloc_allocations[size];
}
另一个对内存使用量的统计通过调用 zmalloc_used_memory 函数返回:
size_t zmalloc_allocations_for_size(size_t size) {
if (size > ZMALLOC_MAX_ALLOC_STAT) return 0;
return zmalloc_allocations[size];
}
if (size > ZMALLOC_MAX_ALLOC_STAT) return 0;
return zmalloc_allocations[size];
}
另外 zmalloc.c 中,还针对不同的系统实现了 zmalloc_get_rss 函数,在linux系统中是通过读取/proc/$pid/stat文件获得系统统计的内存占用量。