Lua数据结构和内存占用分析(5)

使用2的指数倍扩容,针对单个表扩容其实并不频繁,比如100W个节点,最多扩容20次,2^20 > 100W。只是在表的前期会相对频繁,12359条记录插入会触发扩容,所以要避免小表的频繁创建插入。

预先填充方式

 

a = os.clock()

for i = 1, 1000000 do

    local tab = {["1"] = 1, ["2"] = 2, ["3"] = 3, ["4"] = 4, ["5"] = 5}

end

b = os.clock()

print(“timediff:”, b - a)

 

timediff: 0.53

 

动态扩容方式

 

a = os.clock()

for i = 1, 1000000 do

    local tab = {}

    tab["1"] = 1

    tab["2"] = 2

    tab["3"] = 3

    tab["4"] = 4

    tab["5"] = 5

end

b = os.clock()

print(“timediff:”, b - a)

 

timediff: 1.68

 

分析:可以看到预填充方式可以避免频繁的表扩容,cpu消耗是动态扩容的1/3。使用预填充的方式,在创建tab时,会直接分配一个8个元素的Node节点的内存,存放数据。而采用动态扩容的方式,第一次分配1个元素,然后随着数据的插入,会扩容到2个元素的内存,把原来数据重新hash到新分配的内存,释放老内存。同理,随着数据的插入,继而扩容到4个元素、扩容到8个元素...

 

2rehash导致内存消耗演示

tab = {}

text = "diff mem"

collectgarbage("stop")

before = collectgarbage("count");

for i = 1, 100 do

    tab[10000 + i] = i

 

    local cur = collectgarbage("count")

    print(text, cur - before)

    before = cur ;

end

 

 

 

Lua数据结构和内存占用分析

因为hashtable数据分配是012481632这些内存大小,所以在插入数据时分别在123591733时内存不够触发扩容,如上红色标记的点。可以看到在红色标记的点上,内存会有大幅扩大,而且基本是上一次大幅扩容的2倍关系。

 

问题一:在上述截图中,为什么在101834这些地方出现了额外的内存消耗?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/40d90a672028c9263a52f6444ac70320.html