7.3.4 动态数组的扩容方式

本节将介绍当动态数组达到容量上限时是如何进行扩容的。ngx_array_push和ngx_array_push_n方法都可能引发扩容操作。

当已经使用的元素个数达到动态数组预分配元素的个数时,再次调用ngx_array_push或者ngx_array_push_n方法将引发扩容操作。ngx_array_push方法会申请ngx_array_t结构体中size字节大小的内存,而ngx_array_push_n方法将会申请n(n是ngx_array_push_n的参数,表示需要添加n个元素)个size字节大小的内存。每次扩容的大小将受制于内存池的以下两种情形:

❑如果当前内存池中剩余的空间大于或者等于本次需要新增的空间,那么本次扩容将只扩充新增的空间。例如,对于ngx_array_push方法来说,就是扩充1个元素,而对于ngx_array_push_n方法来说,就是扩充n个元素。

❑如果当前内存池中剩余的空间小于本次需要新增的空间,那么对ngx_array_push方法来说,会将原先动态数组的容量扩容一倍,而对于ngx_array_push_n来说,情况更复杂一些,如果参数n小于原先动态数组的容量,将会扩容一倍;如果参数n大于原先动态数组的容量,这时会分配2×n大小的空间,扩容会超过一倍。这体现了Nginx预估用户行为的设计思想。

在以上两种情形下扩容的字节数都与每个元素的大小相关。

注意 上述第2种情形涉及数据的复制。新扩容一倍以上的动态数组将在全新的内存块上,这时将有一个步骤将原动态数组中的元素复制到新的动态数组中,当数组非常大时,这个步骤可能会耗时较长。