回调还是消息队列
前几天在做 Hive 的 socket 库的时候, 遇到一个问题很典型,我记得不是第一次遇到了。值得记录一下。
socket 底层有一个 poll 的 api ,通过 epoll 或 kqueue 或 select 取得一系列的事件。用 lua 怎么封装它呢?
一个比较直接的想法是注入一个 callback function ,对于每个事件回调一个 lua 函数。但这容易引起许多复杂的问题。因为回调函数很不可控,内部可能抛出异常,也可能引起函数重入,或是做了一些你不喜欢去做的事情。
如果面面俱到,就会让原本 C/Lua 边界的性能问题更加恶化。
所以,我采用了方案二:把所有事件以及相关数据全部返回,让后续的 Lua 代码去处理 C 层获取的所有事件。
这个方案也容易造成性能问题,那就是临时构件复杂数据结构,对 Lua VM 的 GC 造成的压力。
为了优化这点,我主张从外部传入一个接收结构的 table ,也就是一个空的消息队列。
然后在 C 层使用 rawseti 把消息加进去。rawseti 是一个相当高效的 lua api 。因为 lua table 如果只有顺序的整数做 key 的话,性能和 C 数组无异。
因为每条消息上有不只一个数据,所以最终的数据结构是一个二维数组。为了不每次临时创建大量的 table ,可以缓存用过的 table 到另一个 table 中。
比如,上次收到 4 条消息,这次收到 5 条的话,就新创建一个 table 保存第 5 条消息关联的参数。下次又收到三条消息的话,就把过剩的两个 table 转移到 cache 中备用。当系统稳定运行后,相当于创建好了整个二维数组接收 C 层产生的数据,而不会临时构建 lua 表了。
再说一个不那么相关的话题:Lua 下实现一个简单的消息队列,我觉得如下简单的几条代码就可以了。
local q1 = {} local q2 = {} -- 产生消息只需要 table.insert(q1, msg) -- 分发消息需要两层循环, 可以处理 dispatch 过程中产生的新消息 while q1[1] do q1,q2 = q2,q1 for i=1,#q2 do dispatch(q2[i]) q2[i] = nil end end
Comments
Posted by: 七分 | (42) September 15, 2014 11:12 PM
Posted by: Cloud | (41) July 16, 2013 06:10 PM
Posted by: yao | (40) July 16, 2013 11:05 AM
Posted by: Cloud | (39) July 15, 2013 05:58 PM
Posted by: yao | (38) July 15, 2013 03:52 PM
Posted by: Anonymous | (37) July 12, 2013 10:50 AM
Posted by: Cloud | (36) July 11, 2013 07:36 PM
Posted by: yao | (35) July 11, 2013 05:55 PM
Posted by: Cloud | (34) July 11, 2013 03:46 PM
Posted by: yao | (33) July 11, 2013 03:45 PM
Posted by: yao | (32) July 11, 2013 09:04 AM
Posted by: yao | (31) July 11, 2013 09:00 AM
Posted by: Cloud | (30) July 10, 2013 10:01 PM
Posted by: Cloud | (29) July 10, 2013 09:43 PM
Posted by: Cloud | (28) July 10, 2013 09:23 PM
Posted by: yao | (27) July 10, 2013 02:23 PM
Posted by: tonyhu | (26) July 10, 2013 12:18 PM
Posted by: tonyhu | (25) July 10, 2013 11:43 AM
Posted by: 路人甲 | (24) July 9, 2013 05:52 PM
Posted by: kkok | (23) July 9, 2013 03:10 PM
Posted by: davidxu | (22) July 9, 2013 11:10 AM
Posted by: 'EXIT' | (21) July 8, 2013 11:45 AM
Posted by: Cloud | (20) July 7, 2013 08:13 PM
Posted by: qiaojie | (19) July 7, 2013 06:17 PM
Posted by: Cloud | (18) July 7, 2013 11:06 AM
Posted by: qiaojie | (17) July 7, 2013 09:03 AM
Posted by: Cloud | (16) July 6, 2013 10:48 PM
Posted by: Cloud | (15) July 6, 2013 10:27 PM
Posted by: qiaojie | (14) July 6, 2013 05:13 PM
Posted by: cloud | (13) July 6, 2013 04:44 PM
Posted by: cloud | (12) July 6, 2013 04:35 PM
Posted by: qiaojie | (11) July 6, 2013 12:32 PM
Posted by: Quon | (10) July 6, 2013 09:51 AM
Posted by: Cloud | (9) July 6, 2013 12:55 AM
Posted by: Cloud | (8) July 6, 2013 12:38 AM
Posted by: 孤单 | (7) July 5, 2013 11:42 PM
Posted by: 小魏 | (6) July 5, 2013 05:02 PM
Posted by: dwing | (5) July 5, 2013 12:18 PM
Posted by: Quon | (4) July 5, 2013 11:06 AM
Posted by: dwing | (3) July 5, 2013 10:35 AM
Posted by: Quon | (2) July 5, 2013 09:56 AM
Posted by: qiaojie | (1) July 5, 2013 12:01 AM