【Nginx】Nginx容器

本文介绍了Nginx中使用的多种数据结构,包括动态数组、动态单向链表、双向链表(队列)、哈希表、红黑树及基数树等,并详细探讨了这些数据结构的应用场景与特点。

1.Nginx中的容器

1.数组
2.链表
3.队列
4.哈希表
5.红黑树
6.基数树

2.数组

确切来说是“动态数组”

多块连续内存,每块连续内存中可以存放许多元素.
/home/muten/module/nginx-1.13.7/src/core/ngx_array.h
typedef struct {
    void        *elts;
    ngx_uint_t   nelts;
    size_t       size;
    ngx_uint_t   nalloc;
    ngx_pool_t  *pool;
} ngx_array_t;

3.链表

确切来说是“动态单向链表”

/home/muten/module/nginx-1.13.7/src/core/ngx_list.h
typedef struct {
    ngx_list_part_t  *last;
    ngx_list_part_t   part;
    size_t            size;
    ngx_uint_t        nalloc;
    ngx_pool_t       *pool;
} ngx_list_t;

4.队列

确切来说是“双向链表”

名字很有误导性哈~~~这其实是一个双向链表,不知道为啥起queue这个名字!!非常不准确!misleading!!!
如果我能给一个名字的话,我会改成double_linked_list_t,一看便知!
/home/muten/module/nginx-1.13.7/src/core/ngx_queue.h
typedef struct ngx_queue_s  ngx_queue_t;
struct ngx_queue_s {
    ngx_queue_t  *prev;
    ngx_queue_t  *next;
};

5.哈希表

/home/muten/module/nginx-1.13.7/src/core/ngx_hash.h

typedef struct {
    void             *value;
    u_short           len;
    u_char            name[1];
} ngx_hash_elt_t;


typedef struct {
    ngx_hash_elt_t  **buckets;
    ngx_uint_t        size;
} ngx_hash_t;



(1)ngx中的hash表与平常我们知道的哈希表的不同(应用场景不同):
ngx_hash通常用于静态不变的内容,在运行的过程中,ngx_hash一般不会出现插入或者删除;
一般nginx刚启动的时候就能确定这个容器里共有多少个元素,所以一般使用ngx_hash的模块
一般会暴露出bucket_size和max_size两个参数,
max_size仅仅控制了最大的bucket_size的个数,而不是实际上bucket_size的个数,
比如说max_size可能配置了100,但实际上只有10个元素使用了hash表,这个max_size
的意义是限制最大化的使用(限制内存的占用量).
(2)ngx中使用哈希表模块的特点
variables(stream/http):变量在模块编译的时候就已经定义清楚了;
map(stream/http):map在模块编译的时候就已经定义清楚了;
反向代理中需要对许多定义好的header做哈希,提升访问性能;
refer,ssi,srcache_filter也是一样的道理,对它们做哈希,可以提升访问性能,访问复杂度是O(1);
(3)哈希表中的bucket size
在bucket size往往有默认值,在我们的Nginx配置文档中的cache line会和这个值关联,
这个实际上影响了如何配置这个bucket_size,现在主流的CPU实际上是由L1,L2,L3缓存的,
实际上去主存(内存)的数据的时候并不是像大家想象的那样按照64位或者32位那样去取,现在主流CPU
一次性从主存中取的字节数是一个cpu cache line,现在是64字节,为什么哈希表要向64字节对齐呢?
因为假设每一个hash表的bucket是59字节,如果我们是紧密地排列在一起的,取第一个哈希表元素只需要
访问一次,还多取了一个字节,但是取第二个元素的时候,就需要访问主存两次,包括第一个64字节中的
最后一个字节和第二个64字节中的58个字节,为了避免这种取两次的问题,Nginx在代码中自动向上对齐,
所以在配置bucket_size的时候要注意两个问题:
一.如果我们配置的不是cpu cache line,如果配置70字节,Nginx会自动向上给我们对齐,给每个元素
分配128字节;
二.如果有可能的话,尽量不要超过64字节,以减少CPU访问每个哈希表元素的次数.



使用Nginx中的ngx_hash_t的时候要注意两点:
(1)ngx_hash_t只为静态的不变的内容服务;
(2)ngx_hash_t的bucket size需要考虑cpu cache line对齐问题.

 

6.红黑树

/home/muten/module/nginx-1.13.7/src/core/ngx_rbtree.h
struct ngx_rbtree_node_s {
    ngx_rbtree_key_t       key;
    ngx_rbtree_node_t     *left;
    ngx_rbtree_node_t     *right;
    ngx_rbtree_node_t     *parent;
    u_char                 color;
    u_char                 data;
};

typedef struct ngx_rbtree_s  ngx_rbtree_t;

struct ngx_rbtree_s {
    ngx_rbtree_node_t     *root;     // 根节点
    ngx_rbtree_node_t     *sentinel; // 哨兵节点
    ngx_rbtree_insert_pt   insert;
};


红黑树:
(1)是个查找二叉树(有序的);
(2)高度差不会太大.

红黑树的特点:
(1)高度不会超过2log(n);
(2)增删改查的算法复杂度O(log(n));
(3)遍历复杂度O(n);


Nginx中使用红黑树的模块或功能点:

 

7.基数树

/home/muten/module/nginx-1.13.7/src/core/ngx_radix_tree.h
struct ngx_radix_node_s {
    ngx_radix_node_t  *right;
    ngx_radix_node_t  *left;
    ngx_radix_node_t  *parent;
    uintptr_t          value;
};


typedef struct {
    ngx_radix_node_t  *root;
    ngx_pool_t        *pool;
    ngx_radix_node_t  *free;
    char              *start;
    size_t             size;
} ngx_radix_tree_t;

是自平衡排序二叉树的一种,只不过key只能是整型,geo模块在使用基数树,其他模块使用的并不多.
基数树对比红黑树:
基数树不需要管是否平衡,插入删除效率远高于红黑树.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值