Lua的一个问题

viagra belgique

最近对qnode进行压力测试,结果很不理想.前期只顾着赶功能,没有进行单元测试,只是简单的进行一些测试,所以现在打算回过头来对一些基础模块写测试用例.

这是本篇的题外话了,在压力测试qnode的时候,由于qnode是使用的actor模型,每个actor会有一个lua协程,但是在做压测的时候,会创建出很多actor这样就出了问题,来看看lua_newthread这个用来创建协程的函数:

LUA_API lua_State *lua_newthread (lua_State *L) {
  lua_State *L1;
  lua_lock(L);
  luaC_checkGC(L);
  L1 = luaE_newthread(L);
  setthvalue(L, L->top, L1);
  api_incr_top(L);
  lua_unlock(L);
  luai_userstatethread(L, L1);
  return L1;
}

这里做的事情很简单,就是创建出lua协程,然后压入lua栈中返回.问题在于,当创建lua协程的操作多起来的时候,每次压入一个数据到lua栈,这样很快lua栈就不够用了.

使用者可以在外部显式的使用lua_pop将这个数据弹出lua栈,但是紧跟着的问题来了:因为这个数据没有与之关联的地方了,会被lua的GC自动回收.

我为此问题翻看了ngx_lua的代码,发现它的处理方式是将lua协程存入一个特定的在registry表中,并且记下索引,当使用者真正需要删除这个数据的时候,再根据这个索引值去将这个数据置空就好了.具体的讨论可以看看这个帖子.

回顾这个问题,让我觉得Lua的设计不够合理,简单的说,我认为设计好的系统应该是对使用者透明无害的,使用者只要按照API文档办事,即使不看其实现也不会犯错.但是很显然,前面列出的这个问题,如果对Lua栈的设计和GC,registry表的实现有一定了解的话,是解决不了的.这个问题的解决代码,也可以看看我在qnode中根据上面的思路写的实现,参见这里的qlua_new_thread函数.

3 Comments

  1. middleware 说:

    64-bit 的 LUAI_MAXSTACK 缺省是 1000000。不够用?不够似乎可以直接修改这个参数吧?

    [回复]

  2. 那谁 说:

    你这个做法只是掩饰了这个问题,不是解决这个问题的做法.

    [回复]

  3. sniperHW 说:

    可考虑在C中实现微线程,替代lua的coroutine

    [回复]

Leave a Reply