一项通用的编程技术:用空间换时间。
例如有一种做法就可以提高一些函数的运行速度,记录下函数计算的结果,当再次调用该函数时,便可以复用之前的结果。
比如,一个普通服务器,在它收到请求中包含Lua代码,会loadstring,编译出新函数。为了避免反复loadstring,用一个辅助table保存编译结果。
local results = {} --辅助的table,记录所有loadstring的结果
function mem_loadstring(s)
local res = results[s]
if res == nil then --是否记录过
res = assert(loadstring(s)) --计算新结果
results[s] = res --存下以备之后复用
end
return res
end
table results会逐渐地积累服务器收到的所有命令及其编译结果。经过一段时间后,这种累积会耗费服务器内存。
弱引用的table可以解决这个问题。如果result table具有弱引用的value,那么每次垃圾收集都会删除所有在执行时未使用的编译结果。
local results = {}
setmetatable(results, {__mode = "v"}) --使value成为弱引用,由于key是字符串,也可以把table变成完全弱引用 __mode = "kv"
function mem_loadstring(s)
<as before>
“备忘录”技术还可以用于确保某类对象的唯一性。
假设一个系统用table来表示颜色,其中3个字段red,green和blue具有相同的取值范围。最简单的颜色生成函数是:
function createRGB(r , g , b)
return {red = r , green = g, blue = b}
end
通过备忘录技术,可以复用具有相同颜色的table,备忘录table的key可以根据颜色分量来生成:
local results = {}
setmetatable(results, {__mode = "v"}
function createRGB(r , g , b )
local key = r .. "-" .. g .. "-" .. b --字符串作为唯一的key,可以通过原始的相等性操作符比较
local color = results[key]
if color == nil then
color = {red = r , green = g, blue = b}
results[key] = color
end
return color
end
若两种颜色相同,那么它们必定是由同一个table表示的。
只要一种颜色正在使用,就不会被清除出results,只要一个颜色未被清除,它就可与颜色进行比较,它的表示也可作为后续调用来复用。
以上内容来自:《Lua程序设计第二版》和《Programming in Lua third edition 》