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


通过对比:在创建不同字符串时,不论长短字符串,都会有一份不同字符串的拷贝,所以都需要消耗大量内存。1052K  VS  1145K

问题一在对比情景2和情景4时,长字符串都是一份拷贝,为什么内存消耗差异较大?(791K vs 1145K)

答:这是因为使用连字符 .. 时,情景4里面的变量i转为字符串,相当于生成了10000份不同的短字符串拷贝,导致多消耗了300K左右内存,所以在开发中可以适当避免 .. 产生大量字符串的产生。可以考虑使用string.format来格式化字符串。具体效果如下:

Lua5.3.4

 

 

 

collectgarbage("stop");      --close auto gc

collectgarbage("collect")    --full gc

for i = 1, 10000 do

    local string = string.format("100000000000000000000000000000000000000000%d", i)

end

 

local after = collectgarbage("count");

print("mem cost:" .. (after - before) .. "K" )

 

 

mem cost:799.7K (结果比较接近情景2)

 
  2.1.2 预估字符串消耗

问题二:以情景2为例,最终内存消耗771.48K,这个可以在开发前估算吗?

答:string实际是GCObject对象,所以有些公共的字段。以”Lua”这个字符串为例,TString的内存结构:

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

在情景2中,实际字符串长度为54。那么内存占用 = sizeof(TString) + 1 + 实际长度 = 25 + 实际长度 = 25 + 54 = 79。理论内存:10000 * 79/ 1024 = 771.48K, 理论跟实际消耗值几乎一致。

2.1.3 与lua5.1.4的对比

  但由于我们之前也用过lua5.1.4,这个版本所有字符串均引用StringTable一份数据拷贝,理论上不论长短字符串,只要相同的数据只会有一份拷贝。(由于lua5.1.4版本在调用collectgarbage("collect")进行一次完整gc后,luaC_fullgc会调用setthreshold打开自动gc,这里容易踩坑,上述代码运行发现内存消耗明显低于lua5.3版本,非常困惑。所以修改代码在collectgarbage("collect")后,重新调用collectgarbage("stop")关闭自动gc)。修改后在lua5.1.4下面执行对比如下:

 

 

Lua5.3.4内存消耗

 

Lua5.1.4内存消耗

 

情景1

相同短字符串

 

0.580078125K

 

0.048828125K

 

情景2

相同长字符串

 

 

771.48K

 

0.0966796875K

 

情景3

不同短字符串

 

 

1052.62109375K

 

1052.62109375K

 

情景4

不同长字符串

 

 

1145.82421875K

 

1305.828125K

 

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

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