Lua垃圾收集策略

Lua自动进行内存的管理。程序只能创建对象,而没有执行删除对象的函数。通过使用垃圾收集技术,Lua会自动删除那些失效的对象,也就是引用为0 的对象。但是呢?有些对象,引用没有指向它,就没办法引用到他,就相当于没法回收的垃圾内存。

一个典型的例子就是堆栈:有一个数组和指向栈顶的索引构成。认为数组中有效的只是在顶端的那一部分,但Lua不那么认为。如果你通过简单的出栈操作提取一个数组元素,那么数组对象的其他部分对Lua来说仍然是有效的。同样的,任何在全局变量中声明的对象,都不是Lua认为的垃圾,即使你的程序中根本没有用到他们。这两种情况下,你应当自己处理,为这种对象赋nil值,防止他们锁住其他的空闲对象。

看下面的例子:

a = {}
key = {} -- creates first key
a[key] = 1 key = {} -- creates second key
a[key] = 2
collectgarbage() -- forces a garbage collection cycle
fork, v inpairs(a) doprint(v) end --> 输出1、2

上面的代码中输出为1 , 2, 第二次采用同样的键值覆盖第一次的数据,但在collectgarbage()并没有是释放第一次引用的数据。除了遍历就不能通过其他途径获取到这个数据了,但对于对象而言,存放在数组中就相当于过一个强引用,Gc当然不会回收了。

Weak Table

我觉得英文的解释更清晰一点,《Lua程序设计》中文描述实在理解不了。还是看下下面的描述吧:

A weak table is a table whose elements are weak references. A weak reference is ignored by the garbage collector. In other words, if the only references to an object are weak references, then the garbage collector will collect this object.

最重要的点是:如果一个对象所有的引用都是weak,对象将被收集,而那些weak引用将会被删除。,如果上面的数组是一个weak table,那第一次数据被覆盖后,只存在weak 引用指向数组对象,所以在collectgarbage时会被当做垃圾收集。

Weak Table方式定义

Weak Table方拥有metatable,元方法 _mode字段定义了指定weak性,__mode字段可以取以下三个值:k、v、kv。k表table.key是weak的,也就是table的keys能够被自动gc;v表示table.value是weak的,也就是table的values能被自动gc;kv就是二者的组合。任何情况下,只要key和value中的一个被gc,那么这个key-value pair就被从表中移除了( In any case, if either the key or the value is collected, the whole pair is removed from the table)。

比如上面的案例,可以设置为weak table来实现垃圾的回收:

a = {}   b = {}
setmetatable(a, b)
b.__mode = \"k\" -- now 'a' has weak keys
key = {} -- creates first key
a[key] = 1 key = {} -- creates second key
a[key] = 2
collectgarbage() -- forces a garbage collection cycle
fork, v inpairs(a) doprint(v) end --> 2

a 变为weak table之后,第二个赋值语句key={}覆盖了第一个key的值。当垃圾收集器工作时,在其他地方没有指向第一个key的引用,所以它被收集了,因此相对应的table中的入口也同时被移除了。可是,第二个key,仍然是占用活动的变量key,所以它不会被收集。

需要注意的:只有对象才可以从一个weak table中被收集。比如数字和布尔值类型的值以及字符串,都是不会被收集的。不过可以将value设置为weak refence,value在没有引用的时候一起将表中对应key-value销毁。

应用案例1-- 记忆函数

localresults = {}
setmetatable(results, {__mode = \"v\"}) -- make values weak
functionmem_loadstring (s)
localresults = {}
functionmem_loadstring (s)
if results[s] then -- result available?
return results[s] -- reuse it
else
localres = loadstring(s) -- compute new result
results[s] = res -- save for later reuse
returnres
end
end

想像一下一个通用的服务器,接收包含Lua代码的字符串请求。每当它收到一个请求,它调用loadstring加载字符串,然后调用函数进行处理。然而,loadstring是一个“巨大”的函数,一些命令在服务器中会频繁地使用。不需要反复调用loadstring和后面接着的closeconnection(),服务器可以通过使用一个辅助table来记忆loadstring的结果。在调用loadstring之前,服务器会在这个table中寻找这个字符串是否已经有了翻译好的结果。如果没有找到,那么(而且只是这个情况)服务器会调用loadstring并把这次的结果存入辅助table。

这个方案的存储消耗可能是巨大的。尽管如此,它仍然可能会导致意料之外的数据冗余。尽管一些命令一遍遍的重复执行,但有些命令可能只运行一次。渐渐地,这个table积累了服务器所有命令被调用处理后的结果;早晚有一天,它会挤爆服务器的内存。一个weak table提供了对于这个问题的简单解决方案。如果这个结果表中有weak值,每次的垃圾收集循环都会移除当前时间内所有未被使用的结果(通常是差不多全部).

带有默认的表

local defaults = {}
setmetatable(defaults, {__mode = \"k\"})
local mt = {__index = function (t) return defaults[t] end}
function setDefault (t, d)
defaults[t] = d
setmetatable(t, mt)
end

结束语

看完Lua交互APi之后为什么要回来看weak表的问题呢?有可能带有GC的语言中都会存在weak ref这样一个概念,至少是解决一种情况下垃圾内存的一种方式。OK ,在Ulua的实现中,C#对象和Lua之间也是通过weaktable建立联系,[C++ Tolua也是采用类似的实现方式][2]。

[2]:http://www.luvfight.me/lua-cpp-object-life-time/ “Cocos2d-x-Lua对象生命周期管理”

Lua 基础之Weak Table(5)的更多相关文章

  1. Lua弱表Weak table

    定义:弱表的使用就是使用弱引用,很多程度上是对内存的控制. 1.weak表示一个表,它拥有metatable,并且metatable定义了__mode字段. 2.弱引用不会导致对象的引用计数变化.换言 ...

  2. lua中的weak table

    weakTable = {} weakTable[] = function() print("i am the first element") end weakTable[] = ...

  3. lua weak table 概念解析

    lua weak table 经常看到lua表中有 weak table的用法, 例如: weak_table = setmetatable({}, {__mode="v"}) 官 ...

  4. Lua中的weak表——weak table

    弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...

  5. Lua中的weak表——weak table(转)

    弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...

  6. Lua基础之table详解

    概要:1.table特性:2.table的构造:3.table常用函数:4.table遍历:5.table面向对象 原文地址:http://blog.csdn.net/dingkun520wy/art ...

  7. lua基础【三】唯一数据结构table表

    --[[ 数据结构table对象(一种动态分配的对象) lua中的表操作.table类型实现了"关联数组的". "关联数组是一种具有特殊索引方式的数组" 能够通 ...

  8. Lua 基础

    Lua 5.3 的中文手册, http://cloudwu.github.io/lua53doc 在线浏览 --第一部分 -- 两个横线开始单行的注释 --[[ 加上两个[和]表示 多行的注释. -- ...

  9. Lua基础 函数(一)

    转自: http://blog.csdn.net/wzzfeitian/article/details/8653101 在Lua中,函数是对语句和表达式进行抽象的主要方法.既可以用来处理一些特殊的工作 ...

随机推荐

  1. 通过反编译深入理解Java String及intern

    一.字符串问题 字符串在我们平时的编码工作中其实用的非常多,并且用起来也比较简单,所以很少有人对其做特别深入的研究.倒是面试或者笔试的时候,往往会涉及比较深入和难度大一点的问题.我在招聘的时候也偶尔会 ...

  2. 反调试手法之CreateProcess反调试

    反调试手法之CreateProcess反调试 在学习Win32 创建进程的时候.我们发现了有一个进程信息结构体. STARTUPINFO. 这个结构体可以实现反调试. 具体CreateProcess可 ...

  3. Netty入门简介

    前言 Netty是一个高性能.异步事件驱动的NIO框架,它提供了对TCP.UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机 ...

  4. LeetCode算法笔记目录

    贪心算法: LeetCode翻转矩阵后的得分-Python3<六> LeetCode根据身高重建队列-Python3<七> LeetCode 任务调度器-Python3< ...

  5. Java并发编程:ThreadLocal的使用以及实现原理解析

    前言 前面的文章里,我们学习了有关锁的使用,锁的机制是保证同一时刻只能有一个线程访问临界区的资源,也就是通过控制资源的手段来保证线程安全,这固然是一种有效的手段,但程序的运行效率也因此大大降低.那么, ...

  6. Mybatis generator代码生成

    背景 项目中使用Mybatis做持久层框架,但由于开发成员水平不一,写dao的时候,各有各的偏好,有时候还会写出带sql注入漏洞的代码. 出现sql注入漏洞,一般是#和$的区别没弄明白: $ 直接把字 ...

  7. hadoop的企业优化

    前言: Mapreduce程序的效率的瓶颈在于两点: 计算机性能: CPU.内存.磁盘健康.网络 I/O操作: 数据倾斜 map和reduce数量设置不合理 map的运行时间太长,导致reduc的等待 ...

  8. PyCharm 添加签名和时间

    工具栏上添加上 Toolbar 点击 Editor -> File and Code Templates -> Python Script 在文本框上填写需要的数据

  9. 洛谷P3193 [HNOI2008]GT考试(dp 矩阵乘法)

    题意 题目链接 Sol 设\(f[i][j]\)表示枚举到位置串的第i位,当前与未知串的第j位匹配,那么我们只要保证在转移的时候永远不会匹配即可 预处理出已知串的每个位置加上某个字符后能转移到的位置, ...

  10. ArcGIS地图文档优化 mxdPerfstat工具使用体验

    经常有客户会咨询到如何提高地图的显示性能.为何ArcMap刷新地图那么缓慢.为何地图服务响应要等待10多秒? 诸如这些问题,虽然它们的表象都是相似的,但是往往在分析排查问题的时候,我们发现背后的原因是 ...