Nginx对内存的使用极其苛刻,达到了令人呕吐的地步。
这里仅仅分析一个hash桶的映射过程中的一小步骤:
计算映射一个数组到hash桶的时候,所需要的桶的多少。
这是图:
源代码:
//假定需要的桶多少是start,由于max_size是桶的最大大小,所以最多就是hinit->max_size
//该函数是进行测试,预想的大小是否可以满足桶的大小的实际需求
for (size = start; size < hinit->max_size; size++) {
//在计算过程中,根本没另外分配内存来存放计算出的每个桶已经”预定放入”的k-v键值对占用内存的多少。
//而是每次使用test这个内存的前size(预想的桶多少)个字节来进行存储。
ngx_memzero(test, size * sizeof(u_short));
for (n = 0; n < nelts; n++) {
if (names[n].key.data == NULL) {
continue;
}
//通过取余运算获知,在当前的预想的桶个数情况下,应该分配到哪个桶。
key = names[n].key_hash % size;
//将该桶的k-v占用内存计数增加
test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
//log级别相关
#if 0
ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
"%ui: %ui %ui /"%V/"",
size, key, test[key], &names[n].key);
#endif
//该桶的k-v占用内存太多了,则进入next,也就是桶数需要增加
if (test[key] > (u_short) bucket_size) {
goto next;
}
}
//成功的计算完成,去found进一步处理计算结果,即包括需要的桶数和每个桶的k-v需要的内存大小
goto found;
//桶的内存超过限定的时候,进入下一次循环的地方(下一次循环,即试探将桶+1是否可以)
next:
continue;
}
虽然处理并不复杂,但是整个通过其不完全符合面向对象逻辑的处理,可以看出作者对内存使用的用心。