做网站从哪里找货源,为什么做网站会被批捕,湖南省金力电力建设有限公司 网站,河源网络公司按照唐老师的课程本来要讲自带库的#xff0c;但是想想这东西能看文档#xff0c;ctrl左键还能看注解#xff0c;并且最重要的许多自带库的方法基本大部分语言都有#xff0c;其实看看就能懂了。所以还是重点讲讲垃圾回收 文章目录 GC辅助垃圾回收collectgarbage增量模式分… 按照唐老师的课程本来要讲自带库的但是想想这东西能看文档ctrl左键还能看注解并且最重要的许多自带库的方法基本大部分语言都有其实看看就能懂了。所以还是重点讲讲垃圾回收 文章目录 GC辅助垃圾回收collectgarbage增量模式分代模式 __gcweak table弱引用表 以下大部分内容摘抄自[Lua]垃圾回收详解lua源码解析——gc实现机制[详细版]一请各位阅读链接中文章 GC
如果你是Unity接触Lua的话应当知道C#中也存在GC机制在面向对象的大部分语言中都使用到了虚拟机而Unity中也使用了Mono 虚拟机。而我们的代码则是在虚拟机的虚拟内存中在虚拟机中代码要转换成指令集编译成字节码最后在各个平台上使用字节码转译的指令集来实现跨平台。
由于对象所占用的内存空间都是存放在虚拟内存中的因此就不会影响到物理内存。当物理内存需要调用对象的时候虚拟内存块就会被指派给物理内存。如果一个虚拟内存块长时间不被物理内存所引用那么它所占的内存应当被释放这就是GCgarage collect
Luc官方doc 根据官方的描述通过GC机制Lua可以自动的管理内存剔除出那些dead objects这些object的类型包括stringtablesuserdatafunctionthreadsinternal structures等等
而那些被认为是dead的对象将不会再程序中被访问但finalizers可以复活这些死亡的物体。GC认为的已死和程序员认为的有所不同GC认为长时间不活动就是死了而如果一个对象被认为死了那么也就无法再正常访问。
通过使用函数collectgarbage或者定义元方法__gc我们可以直接使用或者重写gc机制。 辅助垃圾回收
虽然自动垃圾回收在大多数时候都适用但在一些特殊的情况下还是要我们自己确定垃圾回收的对象和时机。为此Lua语言提供了一下方式来辅助进行垃圾回收
collectgarbage函数允许控制垃圾回收器的步长析构器finalizer允许收集不在垃圾回收器直接控制下的外部对象弱引用表weak table允许收集Lua中还可以程序访问的对象尤其是table中的空键值 collectgarbage
---alias gcoptions
---|collect # 做一次完整的垃圾收集循环。
---| stop # 停止垃圾收集器的运行。
---| restart # 重启垃圾收集器的自动运行。
---| count # 以 K 字节数为单位返回 Lua 使用的总内存数。
---| step # 单步运行垃圾收集器。 步长“大小”由 arg 控制。
---| isrunning # 返回表示收集器是否在工作的布尔值。
---| incremental # 改变收集器模式为增量模式。
---| generational # 改变收集器模式为分代模式。---
---这个函数是垃圾收集器的通用接口。 通过参数 opt 它提供了一组不同的功能。
---
function collectgarbage(opt, ...) end// 使用方法collectgarbage(加内关键字)
collectgarbage(collect) --主动进行一次垃圾回收(垃圾回收会回收nil的垃圾)每次垃圾回收占用内存还是挺多的所以能不用尽量少用能手动就别自动。
collectgarbage提供了两种回收模式分别是增量模式和分代模式
增量模式
在增量模式下每次gc循环使用mark-and-sweep方法来逐步进行垃圾标记和收集GC与解释器一起交替运行Lua5.1及之后不需要停止主程序的运行每当解释器分配了一定数量的内存时垃圾回收器也执行一步。每个GC周期由四个阶段组成分别是标记(mark)、清理(cleaning)、清除(sweep)和析构(finalization)
collectgarbage(incremental,200,200,13)
1、garbage-collector pause, 什么时间执行比上次回收后内增加的比例 默认200% 最大1000%
2、garbage-collector step multiplier,
相对说内存分配而言的一个比例也就是是以什么速度收集 默认 200% 最大 1000%
3、 the garbage-collector step size
控制每次回收的步幅解释器分配的字节数 默认是 2的13次 约 8K以下大部分内容摘自lua源码解析——gc实现机制[详细版]一
上述参数将控制collectgarbage在增量模式下的一些参数增量模式使用mark-and-sweep方法也就是先标记后处理简单地来说使用的是三色标记法把所有的对象都放在树形结构而父子关系可以用一个链表用头插法进行元素增加。
在起始状态所有的节点颜色都是白色。白色代表了未引用 现在引用关系如上图所示那么从根节点开始遍历引用关系并给链表中的节点上色 1号节点有引用所以上色灰色将其头插到链表gray中 接着1号的孩子4号有引用将1号上色黑色并出链表再把四号上色灰色并进链表
接着就重复上述过程4号上色黑色出链表789上色灰色入链表。依次执行知道gray链表中再无节点为止那么所有引用的节点都被上了黑色。
最后就是清理环节sweep节点会顺序遍历rootgc链表所有的白色节点都会被提出如果在清除前有白色节点突然被引用了那么该节点会被上色保护色白色不删除它。整理完毕后再把所有黑色节点置为白色方便下次清理。
分代模式
collectgarbage(generational,20,200)
1,minor比例数相对于上次major回收增长的比例达到即执行minor , 默认20% 最大200%
2), major 比例数内存使用增长比例达到就执行回收默认100最大1000上述参数将控制collectgarbage在迭代模式下的一些参数在分代GC模式中垃圾收集器频繁的执行小型垃圾回收每次都从最近创建的对象中进行扫描清理其中的垃圾而不是扫描所有对象。如果这种小型GC后内存仍然超出限制它将暂停程序的运行遍历所有对象进行GC。 __gc
在元表中同样为gc提供了一种元方法 __gc元方法所定义的函数被官方称为finalizer暂且用知乎上的称呼“析构器”。当这个定义了元方法的对象被gc回收的时候它会执行析构器中的函数。使用这个元方法我们可以在某些对象被清理的时候调用析构器的函数或者为了避免某些对象被清理而将它复活。
例子1
t {name zhangsan}
setmetatable(t,{__gc function (t)print(t.name)
end})
t nil
--调用t的析构函数,打印zhangsan在例子1中打印了zhangsan但是t被gc清理了实际过程是gc开始清理对象-使用析构器,打印t.name(尽管tnil但是被析构器短暂的复活了而执行完析构器之后又会死去)-gc清理
如果一个对象在设置元表时没有为它添加 __gc 元方法而是在元表创建完成后添加那么这个对象在回收时将无法触发 __gc元方法。
t {name zhangsan}
mt {}
setmetatable(t,mt)
--先设置元表,再为元表添加__gc元方法
mt.__gc function (t)print(t.name)
end
t nil
--不会输出任何值(未执行析构器)因为析构器要访问被回收的对象因此Lua需要将这个对象复活(resurrection)。通常这种复活是短暂的这个对象占用的内存将在下次GC时被释放。但是如果析构器将这个对象存储在某个全局位置比如全局变量那么这种复活就会变成永久的。
t {name zhangsan}
setmetatable(t,{__gc function (t)print(t.name)a t --在析构函数中将它赋值给全局变量
end})
t nil
collectgarbage() --在此处要手动垃圾回收,否则由于下方还有语句不会执行gc而a也就不会被赋值了,打印zhangsan
print(a.name) --t引用的对象并未被回收(永久复活),打印zhangsanweak table弱引用表
如果要保存一些活跃对象该怎么做呢我们只需要将它放入table但一个对象一旦加入数table将再也不能被回收因为就算没有其他地方引用它但依然包含在数table中不过我们可以通过**弱引用表weak table**显式告诉Lua这个数table中的引用不应该影响此对象的回收。
弱引用weak reference指的是不在垃圾回收器考虑范围内的引用如果一个对象的引用全是弱引用那么垃圾回收器会回收这个对象并删除这些弱引用弱引用表就是Lua实现弱引用的方式。
一个表是否为弱引用表是由其元表的__mode字段决定的它有三种情况分别是
键弱引用通过设置 __mode k允许垃圾回收器回收它的键但不允许回收值值弱引用通过设置 __mode v允许垃圾回收器回收它的值但不允许回收键。也称为瞬表ephemeron table只有它的键可访问值才能被访问。因为当它的键无法访问时值也会被垃圾回收器从table中移除。键值都为弱引用通过设置 __mode kv键值都允许回收
需要强调的时在任何情况下只要table的键或值被回收整个键值对都会从table中移除。
以下内容摘自Lua基础之弱引用
Lua采用垃圾自动回收的内存管理机制但有时候Lua并不能正确判断对象是否需要被销毁导致某些需要被销毁的对象一直存在造成内存泄漏。
a {}
key {}
print(a[key])
a[key] 1
print(a[key])
key {}
print(a[key])
a[key] 2
collectgarbage()
for k,v in pairs(a) doprint(k, v)
end
输出
nil
1
nil
table: 00000000006da000 1
table: 00000000006da380 2本该销毁的1却没有被销毁尽管key{}之后a[key]是nil但是当我们遍历的时候还是得到了1说明它并没有被销毁。这就是因为这个a[key]是存于table当中的而table中的键值对即使有空也不允许GC删除而这样的情况就会导致内存泄漏。因此为了避免这种情况我们可以使用弱引用来告诉GC机制虽然它是table但里面的空键值都是可以删除的
a {}
b {__mode k}
setmetatable(a,b)
key {}
a[key] 1
key {}
a[key] 2
collectgarbage()
for k,v in pairs(a) doprint(v)
end
输出
2