几种数据结构的性能比较-很惊人


项目中需要用到map类数据结构,key为32位整数。要求支持插入,删除,查找,find_next, find_prev操作,另外要求查找性能好,空间效率也不能差。

于是找到一些实现做了测试,有patricia tree, avl tree, red-black tree, radix tree.

patricia tree: 一种带路径压缩的bitwise trie

avl tree: libavl的实现。用户的数据跟树节点的内存是各自独立申请的,需要通过avl_node->data指针来访问用户数据。

red-black tree: linux kernel的实现。rb_node需要作为用户数据struct的一个字段。

radix tree: linux kernel的实现。它跟patricia都是Trie,但这个实现是每层匹配6个比特。

测试方法很简单:插入size个节点,然后查询100万次。所有的节点都会平均查询若干次。统计不同数据结构的时间消耗。结果如下:

         size=1000    size=2000    size=4000    size=8000    size=16000
patricia    4.760s        5.100s        5.668s        6.632s        6.272s
avl        3.264s        3.548s        3.848s        4.156s        4.472s
rb        1.828s        2.112s        2.364s        2.224s        3.038s
radix       1.552s          1.628s            1.764s      2.544s        3.728s

从结果看出来,这个bitwise patricia性能太差。没有仔细研究其实现,原因不详。

rb tree比avl略快。avl tree平均应该比rb tree更平衡一点,所有平均每次查找所需比较次数更少,理论上说查找效率应该略好(update操作比rb tree慢)。这个avl tree实现效率不够高的原因应该有两个。一是在avl_init的时候,要求传入comparator的函数指针,每次比较都是函数调用。而linux的rb tree可以使用inline或者宏定义的comparator,减少了函数调用的开销。二是avl_node跟用户数据struct不放在一起,每次比较前,需要通过avl_node->data这个指针来访问用户数据struct,增加了cache miss几率。而linux rb tree的rb_node嵌在用户数据struct里面,这样他们往往在同一个cache line,所有效率更高。

radix tree的查找性能应该只跟key的长度有关,跟节点规模无关。但是我的测试结果显示它的scaling还不如查找树。很奇怪。

另外我用valgrind统计了一下它们的内存消耗,结果很惊人。radix tree为每一个key要额外消耗800个字节。而其他三个数据结构,只额外消耗十几个字节。

 

无意中又看见一个据称很高效的tommy trie,测了一下果然很惊人,查找比rb tree快5倍以上,内存消耗也不大,每个节点额外消耗48个字节。先收藏,慢慢研究。


你可能感兴趣的:(数据结构,linux,struct,cache,tree,测试)