在C/C++里面内存比较方便计算:sizeof(struct ranklist) = 114690。可以看到,即使lua的table做了较好的优化,内存优化到早期的1/7, 实际的消耗还是C/C++的2倍。如果记录再增加1条,这个倍数立刻扩大到C/C++内存占用的4倍。所以可以大概认为lua table的一般是C/C++的2 ~ 28(4 * 7) 的范围,当然随着记录条数、table层次不同,这个范围浮动较大,简单可以取个中值算平均数。
正如我们前面分析,lua的table占用内存明显高于C/C++,主要有以下几个因为:
1、lua table支持动态插入,所以为了性能必须要预分配更大内存,减少因为每次的插入而导致重新分配。这样极端情况就会多耗掉一倍的内存。
2、lua table的节点使用的是Node,为了追求通用性,对应kv字段基本都是TValue类型, 而这个类型占用16字节,kv消耗加起来就是32,明显高于C/C++里面简单字段类型的消耗。 当然lua table引入array可以不需要key字段,内存接近省一半。
3、Lua table本身的管理数据有固定56字节,如果是一个很大的表,这个占用比率并不明显。但如果是很多个小表,例如情景1里面的,占用比例就会很大。
4、在实际开发过程中,一般都会表嵌套表,很多层,由于每层都有内存冗余和浪费,这样嵌套下来消耗就会叠加的更明显。
2.2.4 rehash数据重新分布上面只是描述节点不够用时触发内存扩容,数据重新进行hash分布。但如果既有Array数据,又有HashTable数据时,会怎么进行rehash呢?
系统会把所有的key为整数的节点进行统计(包含在array和HashTable的),同时数组最大内存Max_Aarry_Size按2的指数倍增长,然后计算满足条件Key <=Max_Aarry_Size的整数节点数量,当数量 > Max_Aarry_Size/2 就认为array内存能充分利用,使用率超过50%,直到系统找到一个最大的符合条件的Max_Aarry_Size为止。剩下的节点数量进入HashTable, HashTable也是按2的指数倍增长,直到能够装下剩余节点数为止。
因此,通过这个也验证上面的例子中,for i=1, 10000 do tab[10000+i] = 10000+i end为什么使用的HashTable存储的原因了。当Max_Aarry_Size = 2^13=8196时,没有Key落在这个[1, 8196]区间。当Max_Aarry_Size= 2^14=16392时,只有6392条数据落入区间[1, 16392], 区间利用率小于50%。当Max_Aarry_Size= 2^15=32784时,只有10000落入区间[1, 32784], 也不满足利用率的要求。
Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx