lua table vs closure
最近在重构自己写的框架中的定时器模块,需要把回调函数保存起来,大概如下:
function timer_mgr:save_timer( this,callback )
return { this = this,callback = callback}
end -- 创建新定时器
-- @after:延迟N秒后启动定时器
-- @repeated:N秒循环
-- @this:回调对象
-- @callbakck:回调函数
function timer_mgr:new_timer( after,repeated,this,callback )
local timer_id = self:next_id()
self.timers[timer_id] = save_timer( this,callback )
end function timer_mgr:do_timer( timer_id )
local timer = self.timers[timer_id] -- 调用之前保存的定时器回调
return timer.callback( timer.this )
end
正常情况下,用table保存定时器的回调参数,毕竟lua中也没有太多的数据结构可以选择。不过,我们也可以这样用closure来保存:
function timer_mgr:save_timer( this,callback )
return function()
return callback( this )
end
end -- 创建新定时器
-- @after:延迟N秒后启动定时器
-- @repeated:N秒循环
-- @this:回调对象
-- @callbakck:回调函数
function timer_mgr:new_timer( after,repeated,this,callback )
local timer_id = self:next_id()
self.timers[timer_id] = save_timer( this,callback )
end function timer_mgr:do_timer( timer_id )
local timer = self.timers[timer_id] -- 调用之前保存的定时器回调
return timer()
end
这样似乎看起来更优雅更方便一些,不过,频繁创建closure也是很消耗内存和cpu的,需要和table对比一下:
function test_table_object( this,cb )
return { this = this,cb = cb }
end function test_closure_object( this,cb )
return function()
return cb( this )
end
end local function cb()
print("do nothing ...")
end local max = local table_mgr = {}
local closure_mgr = {} function test_table() local beg_m = collectgarbage("count")
local beg_tm = os.clock() for idx = ,max do
table_mgr[idx] = test_table_object( {},cb )
end local end_m = collectgarbage("count")
local end_tm = os.clock() print("table test",end_m - beg_m,end_tm - beg_tm)
end function test_closure() local beg_m = collectgarbage("count")
local beg_tm = os.clock() for idx = ,max do
table_mgr[idx] = test_closure_object( {},cb )
end local end_m = collectgarbage("count")
local end_tm = os.clock() print("closure test",end_m - beg_m,end_tm - beg_tm)
end collectgarbage("stop")
collectgarbage("collect") test_closure()
test_table()
这段代码,分别在win10 - I3 cpu和debian7(虚拟机) - A8 cpu下测试:
closure test 117946.5 0.489
table test 125000.0 0.446 closure test 180446.5 0.75
table test 171875.0 0.72
可以看到,table和closure的消耗其实都差不多。但closure在这个应用场景下就优雅得多,因为可以很方便地传更多的参数,比如:
function timer_mgr:save_timer( this,callback,... )
return function()
return callback( this,... )
end
end function timer_mgr:new_timer( after,repeated,this,callback,... )
local timer_id = self:next_id()
self.timers[timer_id] = save_timer( this,callback,... )
end function timer_mgr:do_timer( timer_id )
local timer = self.timers[timer_id] -- 调用之前保存的定时器回调
return timer()
end
而table要传可变参则不太好处理了,需要另外创建一个table来pack参数,调用时再unpack,或者只用一个table把callback函数和参数存一起,调用时把函数移除再unpack。总而言之,在这种需要保存参数的回调,closure更合适。当然,如果你的回调函数不带参数,那就是另外一码事了。
查了下,之前也有人做了类似的测试,结果也差不多:http://lua-users.org/wiki/ObjectOrientationClosureApproach
lua table vs closure的更多相关文章
- Lua中的closure(闭合函数)
词法域:若将一个函数写在另一个函数之内,那么这个位于内部的函数便可以访问外部函数中的局部变量,这项特征称之为“词法域”. 例:假设有一个学生姓名的列表和一个对应于没个姓名的年级列表,需要根据每个学生的 ...
- lua table integer index 特性
table.maxn (table) Returns the largest positive numerical index of the given table, or zero if the t ...
- 树形打印lua table表
为方便调试lua程序,往往想以树的形式打印出一个table,以观其表内数据.以下罗列了三种种关于树形打印lua table的方法;法一 local print = print local tconca ...
- lua table 排序--满足多条件排序
前提 假设 一个小怪 有三种属性,等级(level).品质(quality).id(pid) 我们需要对他们进行排序,两种排序情况,第一是单一属性排序,比如按照等级进行排序,或者多种属性进行优先级排序 ...
- cocos2d-x lua table数据存储
cocos2d-x lua table数据存储 version: cocos2d-x 3.6 1. 将table转为json http://blog.csdn.net/songcf_faith/art ...
- cocos2d-x lua table与json的转换
cocos2d-x lua table与json的转换 version: cocos2d-x 3.6 1.引入json库 require("src/cocos/cocos2d/json&qu ...
- Lua table使用
days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Th ...
- lua table表
lua table表 语法结构 创建一个 table 直接使用 "{}" 即可 table1 = {} -- 赋值 table1["name"] = " ...
- lua table表判断是否为空
官方手册里早已经给了答案,那就是靠lua内置的next函数 即如此用: a = {} if next(a) == nil then next其实就是pairs遍历table时用来取下一个内容的函数. ...
随机推荐
- OpenStack 虚拟机热迁移流程图
目录 文章目录 目录 源计算节点与目的计算节点之间的交互流程 Nova 和 Neutron 之间的交互流程 源计算节点与目的计算节点之间的交互流程 热迁移主要包括三个阶段: pre_live_migr ...
- jack语言编译器的实现过程
目录: 1, 背景介绍
- shell练习题集合
1. 获取ip或MAC地址(方法不唯一) [root@cicd ~]# ip a| grep 'inet' | awk -F " +" '{print $3}'| awk -F & ...
- HDFS的NameNode与SecondaryNameNode的工作原理
原文:https://blog.51cto.com/xpleaf/2147375 看完之后确实对nameNode的工作更加清晰一些 在Hadoop中,有一些命名不好的模块,Secondary Name ...
- Mac之间的 远程控制
Mac 自带屏幕共享的工具,两台 Mac 之间的设置步骤: 1.主机(被远程控制的电脑)的设置: 系统偏好设置 -->共享 : 选择打开屏幕共享服务: 添加访问用户 或者 允许所有用户: 电脑 ...
- 慎用rm -rf
首先,搞个回收站在~下 .bashrc或者.bash_profile加入 mkdir -p ~/.trash alias rm=trash alias r=trash alias rl='ls ~/. ...
- flask数据库连接池DBUtils
数据库连接池 为啥要使用数据库连接池 频繁的连接和断开数据库,消耗大,效率低 DBUtils可以创建多个线程连接数据库,且一直保持连接,不会断开 执行数据库操作时,由数据池分配线程,当数据池空时,可选 ...
- CG-CTF 南邮 综合题2
个人网站 http://www.wjlshare.tk 0x00前言 主要考了三块 第一块是文件包含获取源码 第二块是通过sql绕过注入获取密码 第三块是三参数回调后门的利用 做这题的时候结合了别人的 ...
- TensorFlow.资料
1.ZC:看来 要用 TensorFlow,基本逃不过 Python了... TensorFlow物体识别——通过机器学习搭建属于自己的物体识别库 - 迷途无归的博客 - CSDN博客.html(h ...
- 删除Vue中无权限的【node_modules】文件
npm install rimraf -g rimraf node_modules