源码文件
src/core/ngx_array.h
src/core/ngx_array.c
设计思路
数组是非常常用的数据结构。为降低使用时的时间开销,Nginx对数组设计做了不少简化:
- 使用从给定内存池中预分配好的储备元素区块;
- 储备元素区块无空闲元素供分配时,尝试从原内存池中分配新的空闲元素,或扩充储备元素区块以完成分配;
- “分配”,或“压入”,只是取得新的空闲元素的首址,不负责创建实际元素;
- “释放”只是调整原内存池的字段,不负责清理实际元素,或者干脆推迟释放时机;
- 使用者可以直接访问数组的各个字段,以取得最佳性能。
数组适用于元素较小、或元素生命周期较短,扩充储备元素区不会跨越内存池中多个ngx_pool_data_t结构体的场景。
数据结构
ngx_array_create(pool, n, size) ngx_array_push()/ ...
| ngx_array_push_n()
| |
+- ngx_palloc()-----\ /---?- ngx_palloc()------\
| | | |
\- ngx_palloc()-------------------\ | |
| | | |
ngx_array_t V | | |
+-------------------+ | | |
/----- | elts | ======================\ |
| +-------------------+ | | H |
| | nelts | -------\ | | H |
| +-------------------+ | | | H |
| /-- | size bytes | | | | H |
| | +-------------------+ | | | H |
| | | nalloc = n | --\ | | | H |
| | +-------------------+ | | | | H |
| | | pool | | | | | H |
| | +-------------------+ | | | | H |
| | | | | | H |
| | | | | | H |
| | /-------------/ | H |
| | | | | | H |
| | | | | | H |
| | V | | | V V
\----> +-------------------+ -+- -+- | +-------------------+
| | elem 0 | A A | | elem 0 |
| / / | | | / /
| / / | | | / /
| | | | | | | |
| +-------------------+ | | | +-------------------+
| | elem 1 | | | | | elem 1 |
| / / | | | / /
| / / | | | / /
| | | | | | | |
-+- +-------------------+ | | | +-------------------+
A | elem 2 | | | | | elem 2 |
| / / | | | / /
| / / | | | / /
V | | | V | | |
--- +-------------------+ | --- | +-------------------+
| unpushed | | | | elem 3 |
/ elements / | | / /
/ / | | / /
/ / | | | |
/ / | | +-------------------|
/ / | | | elem 4 |
/ / | | / /
/ / | | / /
| | V | | |
+-------------------+ --- <----------/ +-------------------+
| extended | | elem 5 |
/ area / / /
/ (in place) / / /
/ / | /
/ / +-------------------|
/ / | unpushed |
/ / / elements /
/ / / /
| = size * n | | |
+-------------------+ +-------------------+
接口函数
ngx_array_create(pool, n, size)
ngx_array_create()负责动态创建一个数组,动作序列如下:
- 从pool中分配ngx_array_t结构体;
- 从pool中分配能容纳n个size大小的元素的储备元素区块;
- 适当地初始化ngx_array_t结构体。
ngx_array_destroy(array)
ngx_array_destroy()负责“释放”数组使用的内存块(实际为推迟释放时机),但不清理其中的各个元素。动作序列如下:
- 如果储备元素区块位于pool的末尾,直接移动pool->current->d.last指针,指向“释放”后的地址;
- 如果ngx_array_t结构体位于pool的末尾,直接移动pool->current->d.lat指针,指向“释放”后的地址;
- 否则什么也不做。
ngx_array_push(array)/ngx_array_push_n(array, n)
ngx_array_push()负责向数组中“压入”一个元素(实际为取得一个空闲元素的首址),动作序列如下:
- 若数组中还有空闲元素,直接取得其首址并返回;
- 若数组的储备元素区块位于pool的储备内存块中最末位置,且其还有size大小的剩余空间,则直接分配新的空闲元素并返回;
- 重新分配新的储备元素区块(原区块的2倍大小)并复制已有元素,将新区块首址存入elts字段后分配新的空闲元素并返回。
ngx_array_push_n()与前者相似,可以一次返回n个新的空闲元素的切片首址。
转自:http://www.ituring.com.cn/article/19056
其他资料 :
http://blog.youkuaiyun.com/livelylittlefish/article/details/6599056
http://blog.youkuaiyun.com/sunhappy2200/article/details/5915189