系统内存占用优化 - Lua

先看一个例子

1. 实际例子

  1. 先造一个100M的文件,文件名为:test-100M。
  dd if=/dev/urandom of=test1 bs=1M count=10
  1. 写一段lua程序读取这个文件。命名为test.lua
local function load_file(path)
   if not path then
        return nil 
   end

  -- 以只读方式打开文件
   local file = io.open(path, "r")
   local content = file:read("*all")
   io.close(file)
end

load_file("test-100M")

while (true) 
do 
end
  1. 使用ps aux 名检测这个进程的内存变化情况。
 while true; do ps aux | grep test.lua; sleep 1; done

可以看到test.lua进程物理内存消耗了399468kb = 390M


image.png

显然在实际场景中,这样的内存消耗是不能接受的,更要命的是在 load_file调用完成后,内存一直没有降下来。

2. 优化过程

通过刚才例子可以看出,test.lua存在两个问题
1). 内存消耗过大;
2). 内存消耗以后一直没有释放。
解决第一个问题思路是重写lua read函数,自己用c实现。
今天重点讨论第二个,怎么在高内存消耗以后,及时的释放掉内存?

    1. 主动调用lua垃圾回收函数
      通过调用collectgarbage("collect") 显示的去回收内存。 这样做是可以释放掉一部分内存,但由于lua虚拟机出于对内存效率的需要,不会将所有内存都还给操作系统。具体情况可以自己实验下。
    1. 将内存消耗过大的操作单独起系统命令执行,设置超时时间,执行完成,进程退出,由操作系统回收这块内存。
    1. 如果lua进程调用了so库或者其他语言的库,那么首先要检测是否有内存泄露导致内存没有及时释放。
    1. 如果调用栈中push的操作过多,会导致,栈空间变大,短时间内无法释放,可以更改数据格式,采用更加节省内存的protobuf格式。
    1. 其它,如果消耗内存的操作不是读文件,而是像字符串拼接、table。那么可以使用table弱表。 字符串拼接可以用table.concat提高内存回收效率。

2. 优化成果展示

优化后的源码(这里主要展示方式1):

local function load_file(path)
   if not path then
        return nil 
   end

  -- 以只读方式打开文件
   local file = io.open(path, "r")
   local content = file:read("*all")
   io.close(file)
end

load_file("test-100M")

while (true) 
do 
end

local mem1 = collectgarbage("count")
print("初始内存:", mem1, "kb")

load_file()

local mem3 = collectgarbage("count")
print("\n垃圾收集前:", mem3, "kb")
collectgarbage("collect")
collectgarbage("collect")
collectgarbage("collect")
local mem4 = collectgarbage("count")
print("\n垃圾收集后:", mem4, "kb")

while (true) 
do 
end

内存使用统计:


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。